22

スレッドがありT1T2スレッドが後に実行され、スレッドが後に実行さT3れるようにするにはどうすればよいでしょうか?T2T1T3T2

この質問は私のインタビューで聞かれました。私は答えませんでした。詳しく説明してください。

4

18 に答える 18

29

これは、最も単純で愚かなアプローチです。

final Thread t1 = new Thread(new T1()); // assume T1 is a Runnable
t1.start();
t1.join();
final Thread t2 = new Thread(new T2());
t2.start();
t2.join();
final Thread t3 = new Thread(new T3());
t3.start();
t3.join();
于 2012-07-18T15:36:26.067 に答える
6

明白で最も単純な方法は、@Assylias によって既に投稿されています。T1 でメソッド create/start T2 を実行し、T2 でメソッド create/start T3 を実行します。

それは、私見ですが、無意味だと思いますが、それは可能です。

Join() を使用したソリューションは、この質問に答えません。スレッドの実行ではなく、スレッドの終了が確実に行われるようにします。面接官がそれを理解できない場合は、とにかく別の仕事を見つける必要があります.

インタビューでは、私の答えは「なぜ*のために?」です。スレッドは通常、あなたが求めていることを正確に回避するために使用されます。

于 2012-07-18T16:54:45.427 に答える
5

それを行う1つの方法は、次のようなものです。複雑ですが。java.util.concurrent.CyclicBarrierこれにはクラスを使用することをお勧めします。

各スレッドは終了時にブール値を設定し、次のスレッドに続行するよう通知します。それはAtomicBooleanクラスですが、synchronizedできるようにする必要がwait()ありnotify()ます。

ロックオブジェクトを渡すか、begin()メソッドをオンT2にする方がクリーンになるT3ため、これらのオブジェクト内にロックを隠すことができます。

final Object lock2 = new Object();
final Object lock3 = new Object();
boolean ready2;
boolean ready3;
...
public T1 implements Runnable {
    public void run() {
        ...
        synchronized (lock2) {
            // notify the T2 class that it should start
            ready2 = true;
            lock2.notify();
        }
    }
}
...

public T2 implements Runnable {
    public void run() {
        // the while loop takes care of errant signals
        synchronized (lock2) {
            while (!ready2) {
                lock2.wait();
            }
        }
        ...
        // notify the T3 class that it should start
        synchronized (lock3) {
            ready3 = true;
            lock3.notify();
        }
    }
}
...
public T3 implements Runnable {
    public void run() {
        // the while loop takes care of errant signals
        synchronized (lock3) {
            while (!ready3) {
                lock3.wait();
            }
        }
        ...
    }
}
于 2012-07-18T15:49:00.460 に答える
4

スレッド T1、T2、および T3 があります。スレッド T2 が T1 の後に実行され、スレッド T3 が T2 の後に実行されるようにするにはどうすればよいでしょうか? または T1、T2、および T3 の 3 つのスレッドがありますか? JavaでシーケンスT1、T2、T3をどのように保証しますか? 問題は基本的に、T3 が最初に、T2 が 2 番目に、T1 が最後に終了する必要があるということです。スレッド クラスの join() メソッドを使用できます。3 つのスレッドを確実に実行するには、最初に最後のスレッド (T3 など) を開始し、逆の順序で join メソッドを呼び出す必要があります (T3 は T2.join を呼び出し、T2 は T1.join を呼び出します)。このように、T1 が最初に終了し、T3 が最後に終了します。

public class Test1 {
    public static void main(String[] args) {
        final Thread t1 = new Thread(new Runnable() {
            public void run() {
                System.out.println("start 1");
                System.out.println("end 1");
            }//run
        });

        final Thread t2  = new Thread(new Runnable() {
            public void run() {
                System.out.println(" start 2 ");
                try {
                    t1.join(2000);
                } catch (Exception e) {
                    e.getStackTrace();
                }
                System.out.println(" end 2");
            }
        }) ;

        final Thread t3 = new Thread( new Runnable() {
            public void run() {
                System.out.println(" start 3 ");

                try {
                    t2.join(4000);
                }catch(Exception e) {
                    e.getStackTrace();
                }
                System.out.println(" end  3 ");
            }
        });
       // we are reversing the order of the start() method
        t3.start();
        t2.start();
        t1.start();


    }
}

出力から、どのスレッドが CPU を取得するかわからないため、スレッドが異なる順序で開始されていることがわかります。これはスレッド スケジューラの決定であるため、何もできません。ただし、スレッドが正しい順序で終了していることがわかります。つまり、T1、T2、T3 の順です。

それを行う別の方法があります。擬似コードは次のとおりです。

t1.start();

    t1.join(); // signals t2 to wait

    if( !t1.isAlive()) {
        t2.start();// if t1 is finished then t2 will start
    }

    t2.join();//signals t3 to wait

    if (!t2.isAlive()) {
        t3.start(); 
    }

完全なプログラムを見てみましょう:

 public class Tic implements Runnable{
   public void run() {
       try {
            for (int i = 0; i < 2; i++) {
                  System.out.println("tic");
            }
    } catch (Exception e) {
        // TODO: handle exception
        e.getStackTrace();
    }
   }
}

public class Tac implements Runnable{
       public void run() {
           try {
                for (int i = 0; i < 2; i++) {
                      System.out.println("tac");
                }
        } catch (Exception e) {
            // TODO: handle exception
            e.getStackTrace();
        }
       }
    }
public class Toe implements Runnable{
       public  void run() {
           try {
                for (int i = 0; i < 2; i++) {
                      System.out.println("toe");
                }
        } catch (Exception e) {
            // TODO: handle exception
            e.getStackTrace();
        }
       }
    }

public class RunThreads1 {
public static void main(String[] args) {
    try {

        Tic tic = new Tic();
        Tac tac = new Tac();
        Toe toe = new Toe();
        Thread t1 = new Thread(tic);
        Thread t2 = new Thread(tac);
        Thread t3 = new Thread(toe);
        t1.start();

        t1.join(); // signals t2 to wait

        if( !t1.isAlive()) {
            t2.start();// if t1 is finished then t2 will start
        }

        t2.join();//signals t3 to wait

        if (!t2.isAlive()) {
            t3.start(); 
        }

    }catch(InterruptedException e) {
        e.printStackTrace();
    }
}
}

出力は次のとおりです。tic tic tac tac toe toe

于 2018-02-05T07:02:23.243 に答える
3

各スレッド (t1 を除く) の開始時に、先行スレッドで join() を呼び出すようにします。エグゼキューターを (スレッドを直接使用する代わりに) 使用することも別のオプションです。セマフォの使用を検討することもできます。T1 は完了時に許可を解放し、T2 は 2 つの許可の取得を試行し、完了したらそれらを解放し、T3 は 3 つの許可の取得を試行する必要があります。join または executor を使用することが推奨される方法です。

于 2012-07-18T15:35:38.913 に答える
3

たとえば、1 つのスレッドが 1、4、5...2 番目の 2、5、8、3 番目の 3、6、9 などを出力すると、出力は 1、2 になるはずです。 ,3,4,5..... 最初のスレッドは 1 を印刷し、2 番目のスレッドに 2 を印刷する機会を与えます..など、

「one」が 1 を出力するとすぐに、cb.wait を呼び出して 2 つにチャンスを与えます。2 回実行すると、同様の方法で 3 つが呼び出され、続行されます。コードで

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

class one implements Runnable{
    CyclicBarrier cb;
    one(CyclicBarrier cb){this.cb=cb;}
    public void run(){
        int i=1;
        while(true)
        {
            System.out.println(i);
            try {
                Thread.sleep(1000);
                cb.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            i=i+3;
        }
    }

}
class two implements Runnable{
    CyclicBarrier cb;
    int i=2;
    two(CyclicBarrier cb){this.cb=cb;}
    public void run(){


        System.out.println(i);
        try {
            cb.await();
            i=i+3;
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


public class oneTwoThree {
    public static void main(String args[]){
        Runnable threePrinter = new Runnable() {
            int i=3;
            public void run() {
                System.out.println(i);
                i=i+3;
            }
        };


        CyclicBarrier bar2 =new CyclicBarrier(1,threePrinter);//, barrier1Action);
        two twoPrinter  =new two(bar2);
        CyclicBarrier bar1 =new CyclicBarrier(1,twoPrinter);

        Thread onePrinter=new Thread(new one(bar1));
        onePrinter.start();
    }
}
于 2013-01-22T19:45:58.287 に答える
3

スレッドもランナブルです。それらを順番に実行するだけです:

t1.run();
t2.run();
t3.run();

これは明らかにほとんど関心がありません。

スレッドを並行して実行したい場合、1 つの解決策は、JMM が次のことを保証するため、各スレッドに次のスレッドを開始させることです

スレッドでの start() の呼び出しは、開始されたスレッドのアクションの前に発生します。

于 2012-07-18T15:27:11.777 に答える
1

私ははるかに簡単な方法で試しました..待機と通知を使用しました.(前の投稿の循環バリアアプローチとは対照的に)。

これは、1、2、3 の 3 つの状態を取得する「State」クラスを使用します (デフォルトは 3)。3 の場合は t1 がトリガーされ、1 の場合は t2 がトリガーされ、2 の場合は t3 がトリガーされます。

クラス: State// int i=3 T1// 1,4,7 を出力... T2// 2,5,8 を出力 T3// 3,6,9 を出力 など、

あなたの意見やコードに問題がある場合はお知らせください。ありがとう。

コードは次のとおりです。

public class State {

    private int state ;

    public State() {
        this.state =3;
    }

    public synchronized int getState() {
        return state;
    }

    public synchronized void setState(int state) {
        this.state = state;
    }


}


public class T1 implements Runnable {

    State s;
    public T1(State s) {
        this.s =s;
    }

    @Override
    public void run() {
        int i =1;

        while(i<50)
        {
            //System.out.println("s in t1 "+ s.getState());

            while(s.getState() != 3)
            {

                synchronized(s)
                {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            }

            synchronized(s)
            {
                //if(s.getState() ==3)

                if(s.getState()==3)
                System.out.println("t1 "+i);
                s.setState(1);
                i = i +3 ;
                s.notifyAll();


            }

        }

    }

}




public class T2 implements Runnable {

    State s;
    public T2(State s) {
        this.s =s;
    }

    @Override
    public synchronized void run() {
        int i =2;

        while(i<50)
        {

            while(s.getState() != 1)
            {

                synchronized(s)
                {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            }

            synchronized(s)
            {
                //if(s.getState() ==3)

                if(s.getState()==1)
                System.out.println("t2 "+i);
                s.setState(2);
                i = i +3 ;
                s.notifyAll();

            }

        }




    }


}



public class T3 implements Runnable {

    State s;
    public T3(State s) {
        this.s =s;
    }

    @Override
    public synchronized void run() {
        int i =3;

        while(i<50)
        {

            while(s.getState() != 2)
            {
                synchronized(s)
                {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            }

            synchronized(s)
            {

                if(s.getState()==2)
                System.out.println("t3 "+i);
                i = i +3 ;
                s.setState(3);
                s.notifyAll();
            }

        }



    }}





    public class T1t2t3 {
        public static void main(String[] args) {

            State s = new State();
            Thread t1 = new Thread(new T1(s));
            Thread t2 = new Thread(new T2(s));
            Thread t3 = new Thread(new T3(s));

            t1.start();
            t2.start();
            t3.start();

        }
    }
于 2015-07-28T06:14:35.887 に答える
1

スレッド T2 が T1 の後に実行され、スレッド T3 が T2 の後に実行されるようにするにはどうすればよいでしょうか?

NOTE: Assuming that it is not about scheduling the threads in the required order 

条件インターフェイスを使用できます。T1 と T2 を調整するcondition1、T2 と T3 を調整するcondition2という 2つ

の条件を 1 つのLockにバインドする必要があります。condition1を T1 と T2 に渡し、 condition2を T2 と T3 に渡します。 そのため、T2 はrunメソッドで condition1 を 待機し、T1 によって通知されます (T1 がタスクを開始/終了した後、T1 の run メソッドから)。同様に、その実行メソッドで条件2 で T3 を待機させます。これは通知されます。




T2による(T2のrunメソッドから、タスクの開始/終了後)。

于 2017-11-18T20:14:05.453 に答える
0

作成された他のトレッドの各トレッドで優先キューを作成します。完了後に適用Thread.joinし、そのスレッドを優先キューから削除してから、キューの最初の要素を再度実行できます。擬似コード:

   pthread [3] my_threads
    my_queue
    for t in pthreads:
         my_queue.queue(t)

   while !my_queue.empty()
      pop the head of the queue
      wait until it complets
      thread.join()

実装は演習として残されているので、次に正しく実行するときは!

于 2012-07-18T15:28:41.690 に答える
0

その方法でn個のスレッドを実行できることを使用しながら、以下のコードを試してください。

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicExecutionOfThreads {

    public static void main(String args[]) {

        int totalNumOfThreads = 10;
        PrintJob printJob = new PrintJob(totalNumOfThreads);

        /*
        MyRunnable runnable = new MyRunnable(printJob, 1);
        Thread t1 = new Thread(runnable);

        MyRunnable runnable2 = new MyRunnable(printJob, 2);
        Thread t2 = new Thread(runnable2);

        MyRunnable runnable3 = new MyRunnable(printJob, 3);
        Thread t3 = new Thread(runnable3);

        t1.start();
        t2.start();
        t3.start();
        */

        //OR

        ExecutorService executorService = Executors
                .newFixedThreadPool(totalNumOfThreads);
        Set<Runnable> runnables = new HashSet<Runnable>();

        for (int i = 1; i <= totalNumOfThreads; i++) {
            MyRunnable command = new MyRunnable(printJob, i);
            runnables.add(command);
            executorService.execute(command);
        }

        executorService.shutdown();

    }
}

class MyRunnable implements Runnable {

    PrintJob printJob;
    int threadNum;

    public MyRunnable(PrintJob job, int threadNum) {
        this.printJob = job;
        this.threadNum = threadNum;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (printJob) {
                if (threadNum == printJob.counter) {
                    printJob.printStuff();

                    if (printJob.counter != printJob.totalNumOfThreads) {
                        printJob.counter++;
                    } else {

                        System.out.println();
                        // reset the counter
                        printJob.resetCounter();

                    }

                    printJob.notifyAll();

                } else {
                    try {
                        printJob.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

}

class PrintJob {
    int counter = 1;
    int totalNumOfThreads;

    PrintJob(int totalNumOfThreads) {
        this.totalNumOfThreads = totalNumOfThreads;
    }

    public void printStuff() {
        System.out.println("Thread " + Thread.currentThread().getName()
                + " is printing");

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public void resetCounter() {
        this.counter = 1;
    }
}
于 2015-08-03T10:37:19.697 に答える
0

スレッド T2 および T3 を開始する前に、スレッド isAlive メソッドを使用します。

Thread t1 = new Thread(new T1()); 
Thread t2 = new Thread(new T2()); 
Thread t3 = new Thread(new T3()); 
t1.start();

if(t1.isAlive()){   

    t2.start();

}

if(t2.isAlive()){

    t3.start();
}
于 2014-05-20T07:00:06.143 に答える
0
package io.hariom.threading;

// 3 つのスレッド T1、T2、および T3 があります。それらが T1、T2、T3 の順序で終了することをどのように保証しますか?

パブリック クラス ThreadTest1 {

public static void main(String[] args) {

    Thread thread1 = new Thread(new MyRunnable(null));
    Thread thread2 = new Thread(new MyRunnable(thread1));
    Thread thread3 = new Thread(new MyRunnable(thread2));
    thread1.start();
    thread2.start();
    thread3.start();

}

}

class MyRunnable は Runnable { Thread t; を実装します。

MyRunnable(Thread t) {
    this.t = t;

}

@Override
public void run() {
    if (t != null) {
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println(Thread.currentThread().getName() + " starts");
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println(Thread.currentThread().getName() + " ends");
}

}

于 2021-03-12T12:06:32.540 に答える
0

これが、シグナリングにCountDownLatchを使用した問題に対する私のアプローチです。

ジョブ信号を T2 に、T2 から T3 に実行した後の T1 スレッド。


public class T1T2T3 {
  public static void main(String[] args) {

    CountDownLatch c1 = new CountDownLatch(1);
    CountDownLatch c2 = new CountDownLatch(1);
    Thread T1 = new Thread(new Runnable() {

      @Override
      public void run() {
        System.out.println("T1");
        c1.countDown();
      }
    });
    Thread T2 = new Thread(new Runnable() {
      @Override
      public void run() {
        //should listen to something from T1
        try {
          c1.await();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("T2");
        c2.countDown();
      }
    });
    Thread T3 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          c2.await();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("T3");
      }
    });

    T1.start();
    T3.start();
    T2.start();
  }
}
于 2022-01-23T15:50:44.227 に答える