2

私の仕事は、次の順序でスレッドを作成することです。A の場合は B と C を開始し、B の場合は D を開始します。そして、D の場合は B の場合、逆の順序でそれらを破棄します。B と C の場合は A の場合。それ。私はそれを行うことができますが、それを行うより良い方法があると思います。何か提案はありますか?

あなたのコメントの後、私は自分のコードを変更しました。それははるかに簡単です。しかし、今では「ばか」に見えます。if 文と実装のハードコアを変更したいのですが、何かアドバイスはありますか? tnx アドバイスをお願いします 私はあなたと一緒に学んでいます。

これは私の新しいコードです:

     import java.util.*;
class RobotController implements Runnable{
String name;

public void run() {
    Thread t = Thread.currentThread();
    System.out.println(t.getName() + " status = " + t.isAlive());
    System.out.println(t.getName() + " status = " + t.getState());

  }

public static void main(String args[]) throws InterruptedException{
    Thread thread_A = new Thread(new RobotController(), "Thread A");
    Thread thread_B = new Thread(new RobotController(), "Thread B");
    Thread thread_C = new Thread(new RobotController(), "Thread C");
    Thread thread_D = new Thread(new RobotController(), "Thread D");

    thread_A.start();
    thread_A.join();
    System.out.println(thread_A.getState());
    thread_B.start();
    thread_B.join();
    System.out.println(thread_B.getState());
    thread_C.start();
    thread_C.join();
    System.out.println(thread_C.getState());
    thread_D.start();
    System.out.println(thread_D.getState());


}

}
4

4 に答える 4

3

コードにはいくつかの欠陥があり、適切に機能しない場合があります。

  1. に電話thread_A.start()して確認しthread_A.isAlive()ました。thread_A.isAlive()条件がチェックされる前に、thread_A が既に完了している場合はどうなるでしょうか。thread_B開始さthread_Cれません。アプリケーションは失敗します。
  2. が完了thread_Aせず、thread_A.isAlive()条件が渡された場合、Java スレッド スケジューラによって常にthread_B前の開始がthread_C保証されるとは限りません。再びアプリケーションは失敗します。
  3. thread_Bthat starts beforeを想定しthread_C、 if thread_Bcompletes beforethread_B.isAlive()がチェックされた場合、if条件は失敗し、thread_D決して開始されません。再びアプリケーションは失敗します。

熟考するポイント:メソッドが呼び出された
後にスレッドが生きているかどうかを確認する必要はありません。join()これは不要なランタイム オーバーヘッドです。

編集
OK、これがコードの修正版です..スレッドのダイナミクスを理解できることを願っています:

class RobotController implements Runnable
{
    private final Object lock = new Object();
    private void notifyThread()
    {
        synchronized(lock)
        {
            lock.notify();
        }
    }
    public void run() 
    {
        synchronized(lock)
        {
            try
            {
                System.out.println(Thread.currentThread().getName() + " started");
                lock.wait();
                System.out.println(Thread.currentThread().getName()+ " stopped");
            }
            catch (InterruptedException ex)
            {
                ex.printStackTrace();
            }
        }
    }

    public static void main(String args[]) throws InterruptedException
    {
        RobotController rca = new RobotController();
        RobotController rcb = new RobotController();
        RobotController rcc = new RobotController();
        RobotController rcd = new RobotController();


        Thread thread_A = new Thread(rca,"Thread A");
        Thread thread_B = new Thread(rcb,"Thread B");
        Thread thread_C = new Thread(rcc,"Thread C");
        Thread thread_D = new Thread(rcd,"Thread D");

        thread_A.start();
        while (thread_A.getState() != Thread.State.WAITING)
        {
            Thread.sleep(100);
        }
        thread_B.start();
        thread_C.start();
        while (thread_B.getState() != Thread.State.WAITING && thread_C.getState() != Thread.State.WAITING)
        {
            Thread.sleep(100);
        }
        thread_D.start();
        while (thread_D.getState() != Thread.State.WAITING)
        {
            Thread.sleep(100);
        }
        rcd.notifyThread();
        thread_D.join();
        rcc.notifyThread();
        thread_C.join();
        rcb.notifyThread();
        thread_B.join();
        rca.notifyThread();
    }

}

出力は次のとおりです。

Thread A started
Thread B started
Thread C started
Thread D started
Thread D stopped
Thread C stopped
Thread B stopped
Thread A stopped
于 2013-06-13T11:16:16.257 に答える
0

synchronized (lock)私の意見では、オブジェクトをロックするために run メソッドを使用するのは非常に奇妙です。その理由は、各オブジェクトには、各オブジェクトに属するThread異なる属性があるためです。lockこれは、さまざまなオブジェクトをロックしようとしていることを意味します。実際、それは意味がありません。

基本的に、適用するsynchronizedオブジェクトは共有オブジェクトです。たとえば、何かを数える必要があり、それをクラスで共有するクラス オブジェクトを作成します。この場合、読み取りまたは書き込み中はロックする必要があります。

于 2013-06-12T18:11:13.773 に答える
0

ここでは、次の 2 点を強調したいと思います。

  1. ここでスレッド実行ライフサイクルを見てください。start() メソッドが呼び出されると、スレッドは実行可能状態ではなく実行可能状態になるということです。スレッドが実行中の状態になると、それは run() メソッドが実行されていることを意味します。CPU/OS は、実行可能なスレッドから実行中のスレッドに転送するスレッドの優先順位を決定します。たとえば、4 つのスレッドに対して start() メソッドを呼び出す場合、それらが特定の順序で実行される必要はありません。(PC で同じプログラムを複数回実行すると、異なる出力が得られます。

あなたの場合、条件 if(thread_A.isAlive()) が実行されると、スレッド A が実行状態にない可能性があります。したがって、どちらが正しくない場合、コントロールは入りません。この動作を修正するには、メインで、スレッドが有効になるまで待機する while ループを実装する必要があります。

2. プログラムでは、スレッドに名前を割り当てておらず、run() メソッドで名前を出力しています。この場合、JVM は実行順に名前をスレッドに割り当てます。たとえば、最初に実行するスレッドの名前は「Thread-0」などになります。したがって、どのスレッドが最初に実行されたかを特定することはできません。setName() メソッドを使用して名前を割り当てます。

于 2013-06-13T09:42:46.123 に答える