0

重複の可能性:
毎回特定の順序で3つのスレッドをループしようとしています

同じオブジェクトの2つの異なるメソッドに2つのスレッドから次々にアクセスしたいと思います。これが私のコードです、

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 スレッドを終了するまで実行し、次にワールド スレッドを終了するまで実行することによって完全に満たすことができます (作成したプログラムで)

2 つのスレッド間で共有される何らかのトークンを導入し、そのトークンを往復させる必要があります。

トークンは、hello が出力された場合は true、world が出力された場合は false となるブール値のような単純なものにすることができます。

次に、各スレッドは、ブール値が期待される状態と一致するまで、スピンする (または条件を待機する - 条件を使用するとパフォーマンスが向上する) 必要があります。

最も優れた「実際の Java 並行性」の本を手に入れることをお勧めします。

于 2012-09-12T12:40:09.593 に答える
0

これは本質的にシングルスレッドのタスクであるため、このタスクは確かに少し奇妙です。ただし、アプリケーションが非常に複雑になり、複数のスレッドを使用するなど、多くの奇妙なことが必要になる場合があることはわかっています。

Object「イベント」として使用するなど、任意のタイプのプライベート オブジェクトを 2 つ作成できます。各スレッドのループはwait()、イベント オブジェクトの 1 つに対して実行し、次にそのタスクを実行 (文字列を出力) し、次にnotify()別のイベント オブジェクトを実行してから、ループを繰り返しますwait()。別のスレッドが同じことを行う必要がありますが、イベント オブジェクトがスワップされます。

両方のスレッドを開始してからnotify()、最初のイベント オブジェクトを開始します。アクションが始まります!

于 2012-09-12T12:40:08.423 に答える