0

可能重复:
每次都尝试以特定顺序循环 3 个线程

我想一个接一个地从两个线程访问同一对象的两个不同方法。这是我的代码,

public class ThreadCoordination
{
private Thread threadSayHello;
private Thread threadSayWorld;
private boolean threadSayWorldStarted = false;

public ThreadCoordination()
{
    createThreads();
}

private void createThreads()
{
    threadSayWorld = new Thread(new Runnable()
    {
        public void run()
        {
            try
            {
                // while (true)
                {
                    sayWorld();
                }
            }
            catch (InterruptedException ex)
            {}
        }
    });

    threadSayHello = new Thread(new Runnable()
    {
        public void run()
        {
            try
            {
                // while (true)
                {
                    sayHello();

                    if (!threadSayWorldStarted)
                    {
                        threadSayWorldStarted = true;
                        threadSayWorld.start();
                    }
                }
            }
            catch (InterruptedException ex)
            {}
        }
    });

    threadSayHello.start();
}

private synchronized void sayHello() throws InterruptedException
{
    System.out.print("Hello ");
}

private synchronized void sayWorld() throws InterruptedException
{
    System.out.println("World!");
}

public static void main(String[] args)
{
    new ThreadCoordination();
}
}

如果我取消注释调用 while(true),那么我会期待这样的输出,

Hello World!
Hello World!
Hello World!
Hello World!
...

请指导我该怎么做。拉贾。

我不知道我是否可以编辑已关闭的帖子。据我所知,我只想发布解决方案。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class SequenceAccess
{
private ReentrantLock myLock;
private Condition ensureSequence;
private int sequenceNo = 1;

public SequenceAccess()
{
    myLock = new ReentrantLock();
    ensureSequence = myLock.newCondition();

    startThreads();
}

private void startThreads()
{
    new Thread(new Runnable()
    {
        public void run()
        {
            try
            {
                while (true)
                    method1();
            }
            catch (InterruptedException ex)
            {}
        }
    }).start();

    new Thread(new Runnable()
    {
        public void run()
        {
            try
            {
                while (true)
                    method2();
            }
            catch (InterruptedException ex)
            {}
        }
    }).start();

    new Thread(new Runnable()
    {
        public void run()
        {
            try
            {
                while (true)
                    method3();
            }
            catch (InterruptedException ex)
            {}
        }
    }).start();
}

private void method1() throws InterruptedException
{
    myLock.lock();
    try
    {
        while (sequenceNo != 1)
            ensureSequence.await();

        sequenceNo = 2;
        System.out.println("Method 1");
        ensureSequence.signalAll();
    }
    finally
    {
        myLock.unlock();
    }
}

private void method2() throws InterruptedException
{
    myLock.lock();
    try
    {
        while (sequenceNo != 2)
            ensureSequence.await();

        sequenceNo = 3;
        System.out.println("Method 2");
        ensureSequence.signalAll();
    }
    finally
    {
        myLock.unlock();
    }
}

private void method3() throws InterruptedException
{
    myLock.lock();
    try
    {
        while (sequenceNo != 3)
            ensureSequence.await();

        sequenceNo = 1;
        System.out.println("Method 3");
        ensureSequence.signalAll();
    }
    finally
    {
        myLock.unlock();
    }
}

public static void main(String[] args)
{
    new SequenceAccess();
}
}
4

2 回答 2

1

JVM不保证线程执行的顺序

事实上,JVM 规范可以完全通过运行 hello 线程直到它终止,然后运行 ​​world 线程直到它终止(使用你的程序编写)

您将需要引入某种令牌以在两个线程之间共享,然后让该令牌来回穿梭。

令牌可以像布尔值一样简单,如果已经输出 hello,则为 true,如果已输出 world,则为 false。

然后每个线程将不得不旋转(或等待条件 - 条件更好的性能),直到布尔值匹配其预期状态。

我建议您阅读最优秀的“Java 并发实践”一书

于 2012-09-12T12:40:09.593 回答
0

该任务确实有点奇怪,因为这本质上是一个单线程任务。不过,我知道应用程序可能会变得非常复杂,并且需要许多奇怪的东西,而且还有多个线程。

您可以创建两个任何类型的私有对象,例如Object用作“事件”。每个线程的循环应该wait()针对其中一个事件对象,然后执行其任务(打印字符串),然后是notify()另一个事件对象,然后重复循环wait()。另一个线程应该做同样的事情,但交换了事件对象。

启动两个线程,然后启动notify()第一个事件对象。行动开始!

于 2012-09-12T12:40:08.423 回答