0

メソッドを共有する 2 つのスレッドを実行して、何かを出力したいと考えています。これを出力として欲しい:

a b a b a b 

最初のスレッドは「a」を出力し、2 番目のスレッドは「b」を出力します。なんとか一度は印刷できたのですが、印刷物を交換するための適切なループを含めることができません。

これを実行するためにこのコードを書きました:

public void run() {
    while(i<10) {
        synchronized(this) {
            while (turn!=turn) {
                try {
                    turn=!turn;
                    wait();
                    sleep(10);
                }
                catch(InterruptedException ie){}
            }

            printThreadOutput();
            turn=!turn;
            i++;
            notifyAll();
        }
    }
}

助言がありますか?

4

3 に答える 3

1

簡単な解決策は、必要なすべての待機操作と通知操作を実行するjava.util.concurrent.locks.Lockを使用することです。

public class ThreadTest {

    private static final Lock lock = new ReentrantLock();

    public static final void main(String[] args) {
        Runnable aRun;
        Runnable bRun;

        aRun = new Runnable() {
            public void run() {
                while (true) {
                    lock.lock();
                    System.out.println("a");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    lock.unlock();
                }
            }
        };

        bRun = new Runnable() {
            public void run() {
                while (true) {
                    lock.lock();
                    System.out.println("b");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    lock.unlock();
                }
            }
        };

        Thread aThread = new Thread(aRun);
        Thread bThread = new Thread(bRun);
        aThread.start();
        bThread.start();
    }

}

モニターを使用しなくても、このように実行できますが、@noahz が謙虚に指摘しているように、効率的ではないスピンロックを使用します。

public class ThreadTest {

    private static volatile Boolean isATurn = true;

    public static void main(String[] args) {
        Runnable aRun;
        Runnable bRun;

        aRun = new Runnable() {
            public void run() {
                while (true) {
                    while (!isATurn) {
                    }
                    System.out.println("a");
                    isATurn = false;
                }
            }
        };

        bRun = new Runnable() {
            public void run() {
                while (true) {
                    while (isATurn) {
                    }
                    System.out.println("b");
                    isATurn = true;
                }
            }
        };

        Thread aThread = new Thread(aRun);
        Thread bThread = new Thread(bRun);
        aThread.start();
        bThread.start();
    }

}

私が知る限り、これによりデッドロックが発生しないことが保証されますが、スレッドの 1 つが終了しないと、他のスレッドが待機しているため、飢餓が発生する可能性があります。ただし、このような単純な例では問題になりません。モニターもポーリングを使用するよりも優先されますが、少し複雑になります。

于 2013-03-31T01:20:16.250 に答える
0
  1. while の 5 秒前にスレッドの 1 つをスリープさせます。どちらが糸順になるかが明確になります。
  2. while条件が always であるため、ループは実行されていませんfalsewhile中身は必要ありませんので取り外してください。
  3. turn変数は必要ありません。synchronizeと は、Thread.sleep(5)スレッドを交互に実行します。
  4. printlnをキャッチするときは、少なくともいくつか入れてくださいInterruptedException
于 2013-03-31T01:20:11.740 に答える