两个线程如何在java中一个接一个地访问同一个对象的两个方法

时间:2012-09-12 12:17:29

标签: java multithreading synchronization

  

可能重复:
  Trying to loop 3 threads in a specific order everytime

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

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();
}
}

如果我在(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();
}
}

2 个答案:

答案 0 :(得分:1)

JVM 不保证线程执行的顺序

事实上,JVM规范可以完全通过运行hello线程直到它终止然后运行world线程直到它终止(程序已写入)来满足

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

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

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

我建议您掌握最优秀的“实践中的Java并发”一书

答案 1 :(得分:0)

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

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

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