1

スレッド 1 が 1000 ミリ秒ごとに PING を出力し、スレッド 2 が 2000 ミリ秒ごとに PONG を出力する単純なマルチスレッドの例を実装しています。

public class T extends Thread 
{
public void run()
{
int i =10;
while(i>0)
{
    if(Thread.currentThread().getName().equals("T1"))
    {
        System.out.println("\nPING");
        try {Thread.sleep(1000);} 
        catch (InterruptedException e) {e.printStackTrace();}   
    }
    else if (Thread.currentThread().getName().equals("T2"))
    {
        System.out.println("\nPONG");
        try {Thread.sleep(2000);} 
        catch (InterruptedException e) {e.printStackTrace();}
    }
i--;
}
}

public static void main(String[] args) 
{
    Thread t1 = new T();
    Thread t2 = new T();
    t1.setName("T1");
    t2.setName("T2");
    t1.start();
    t2.start();
}
}

しかし、出力は次のようになります::

ポン

ピン

ピン

ピン

ポン

ピン

ピン

ポン

ピン

ピン

ポン

ピン

ピン

ポン

ピン

ポン

ポン

ポン

ポン

ポン

しかし、私の期待される出力は次のようになるはずです

PING
PING
PONG
PING
PING
PONG
PING
PING
PONG.....

コードにどのような変更を加える必要がありますか?

4

6 に答える 6

0

まず、while ループの代わりに for ループを使用する必要があります。それはあなたの意図をより明確にします。次に、スレッドが起動した順序で実行されることが保証されていないことを理解する必要があります。保証されているのは、カーネルが基になるオペレーティング システムの動作方法に従ってスレッドへのタイムスライスの割り当てを開始し、カーネルが待機することだけです。スレッドがスリープするために指定した最小時間 (カーネルが合体スレッドをサポートしている場合は、さらに短いこともあります)。

これは、T1 が実際にはラウンドで 996 ミリ秒待機し、T2 が別のラウンドで 2026 ミリ秒待機する可能性があることを意味します。たとえば、このコードを実行すると、次の出力が得られました。
PING
PONG
PING
PING
PONG
PING
PING
PONG
PING
PONG
PING
PING
PONG
PING
PING
PONG
PONG
PONG
PONG
PONG

ちょっとした混乱。現在、多くのマルチスレッド アプリケーションでは、スレッドが相互に依存していなければ問題ありません。ただし、出力を期待どおりに並べたい場合は、他の回答が示唆するように、wait() と notify() を使用する必要があります。

たとえば、T1 で開始し、次に T1 で T2 を開始します。T2 は実行時にすぐに待機する必要があり、T1 は PING するたびに T2 に通知する必要があります。その後、T2 は通知を受信した回数をカウントし、カウントが偶数の場合は常に PONG を出力できます。

演習として、実装を開いたままにします。

于 2013-10-16T19:11:14.263 に答える
0

新しい並行パッケージの ThreadPool を使用します。

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)

于 2013-10-16T19:07:10.733 に答える