有线程T1
,T2
和T3
,我们如何确保线程T2
在T1
和线程T3
之后运行在T2
之后?
我的采访中提到了这个问题。我没回答。请详细解释。
答案 0 :(得分:21)
这将是最简单,最愚蠢的方法:
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();
答案 1 :(得分:4)
@Assylias已经发布了一种明显且最简单的方法 - 有T1运行方法创建/启动T2和T2运行方法创建/启动T3。
恕我直言,这一点毫无意义,但可以做到。
使用Join()的解决方案不回答问题 - 它们确保线程的终止是有序的,而不是它们的运行。如果面试官没有得到这个,你还是需要找另一份工作。
在接受采访时,我的答案是'为了 * 为什么?线程通常用来避免你所要求的!'。
答案 2 :(得分:3)
这样做的一种方法如下。虽然这很复杂。您可能希望使用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();
}
}
...
}
}
答案 3 :(得分:2)
线程也是可运行的。您可以按顺序运行它们:
t1.run();
t2.run();
t3.run();
这显然没什么兴趣。
假设他们希望线程并行运行,一个解决方案就是让每个线程开始下一个线程,因为the JMM guarantees that:
在启动线程中的任何操作之前,对线程的start()调用发生。
答案 4 :(得分:2)
在每个线程的开头(t1除外),让它在它的前身上调用join()。使用执行程序(而不是直接使用线程)是另一种选择。人们还可以看一下使用信号量--T1应该在完成时释放许可证,T2应该尝试获得两个许可证,并在完成后释放它们,T3应该尝试获得三个许可证和等等。使用连接或执行器将是首选路由。
答案 5 :(得分:1)
猜猜是什么面试官要求三个线程按顺序完成工作。例如,如果一个线程打印1,4,5 ...第二个2,5,8和三个3,6,9等。输出应该是1,2,3,4,5 ..... Ist线程打印1并有机会第二个线程打印2..etc。,
我尝试使用cyclebarriers。只要'one'打印1it就有机会两个,因为它调用cb.wait,当两个运行时它将以类似的方式调用三个并且它将继续。让我知道是否thr是代码中的任何错误
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();
}
}
答案 6 :(得分:1)
有线程T1,T2和T3,我们如何确保线程T2运行 T1和线程T3在T2之后运行? 要么 有三个线程T1,T2和T3?如何确保Java中的序列T1,T2,T3? 问题基本上是T3应该先完成,T2秒和T1最后。 我们可以使用线程类的join()方法。 要确保执行三个线程,您需要先启动最后一个线程,例如T3然后以相反的顺序调用连接方法,例如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。它是Thread Scheduler的决定,因此我们无能为力。但是,你可以看到线程以正确的顺序完成,即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();
}
}
}
输出是: 抽搐 抽搐 TAC TAC 脚趾 趾
答案 7 :(得分:1)
我尝试了一种更简单的方式..使用等待并通知。(与我的上篇文章中的循环屏障方法相反)。
它使用了一个&#39;州&#39; class ...获得三种状态:1,2,3。(默认为3)。 当它为3时,触发t1,1触发t2,2触发t3,依此类推。
类: 状态// 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();
}
}
答案 8 :(得分:0)
package io.hariom.threading;
//你有三个线程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 { 线程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");
}
}
答案 9 :(得分:0)
我们怎样才能确保线程T2在T1之后运行而线程T3在T2之后运行?
NOTE: Assuming that it is not about scheduling the threads in the required order
我们可以使用Condition界面。
我们需要两个条件绑定到一个Lock: condition1 来协调T1和T2, condition2 来协调T2和T3。
传递< strong> condition1 到T1和T2, condition2 到T2和T3。
因此,我们将在 condition1 中使用 condition1 运行方法,该方法将由T1 发出信号(来自T1的运行方法,T1启动后) /完成它的任务)。
同样在它的run方法中 condition2 上有T3 等待,它将发出信号通过T2(来自T2的run方法,在它启动/完成它的任务之后)。
答案 10 :(得分:0)
通过使用连接,您可以确保一个接一个地运行线程。
class MyTestThread implements Runnable{
public void run() {
System.out.println("==MyTestThread : START : "+Thread.currentThread().getName());
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " :i = "+i);
}
System.out.println("==MyTestThread : END : "+Thread.currentThread().getName());
}
}
public class ThreadJoinTest {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new MyTestThread(), "t1");
Thread thread2 = new Thread(new MyTestThread(), "t2");
thread1.start();
thread1.join();
thread2.start();
thread2.join();
System.out.println("====All threads execution===completed");
}
}
答案 11 :(得分:0)
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
class Worker implements Runnable {
BlockingQueue<Integer> q = new LinkedBlockingQueue<>();
Worker next = null; // next worker in the chain
public void setNext(Worker t) {
this.next = t;
}
public void accept(int i) {
q.add(i);
}
@Override
public void run() {
while (true) {
int i;
try {
i = q.take(); // this blocks the queue to fill-up
System.out.println(Thread.currentThread().getName() + i);
if (next != null) {
next.accept(i + 1); // Pass the next number to the next worker
}
Thread.sleep(500); // Just sleep to notice the printing.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PrintNumbersSequentially {
public static void main(String[] as) {
Worker w1 = new Worker();
Worker w2 = new Worker();
Worker w3 = new Worker();
w1.setNext(w2);
w2.setNext(w3);
w3.setNext(w1);
new Thread(w1, "Thread-1: ").start();
new Thread(w2, "Thread-2: ").start();
new Thread(w3, "Thread-3: ").start();
//Till here all the threads have started, but no action takes place as the queue is not filled for any worker. So Just filling up one worker.
w1.accept(100);
}
}
我认为这可以帮助你。
答案 12 :(得分:0)
并发包具有更好的类来使用共享对象。 其中一种方式就是这样。
public static void main(String[] args) {
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
ThreadId threadId = new RunInSequence.ThreadId();
threadId.setId(1);
Thread t1 = setThread("thread1",lock, condition, 1, 2, threadId);
Thread t2 = setThread("thread2",lock, condition, 2, 3, threadId);
Thread t3 = setThread("thread3",lock, condition, 3, 1, threadId);
t1.start();
t2.start();
t3.start();
}
private static class ThreadId {
private int id;
public ThreadId() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
private static Thread setThread(final String name,final Lock lock, final Condition condition, int actualThreadId, int nextThreadId,
ThreadId threadId) {
Thread thread = new Thread() {
@Override
public void run() {
while (true) {
lock.lock();
try {
while (threadId.getId() != actualThreadId) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+"prints: " + actualThreadId);
threadId.setId(nextThreadId);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
};
return thread;
}
答案 13 :(得分:0)
package thread;
class SyncPrinter {
public static void main(String[] args) {
SyncPrinterAction printAction1 = new SyncPrinterAction(new int[]{1,5,9,13}, true);
SyncPrinterAction printAction2 = new SyncPrinterAction(new int[]{2,6,10,14}, true);
SyncPrinterAction printAction3 = new SyncPrinterAction(new int[]{3,7,11,15}, true);
SyncPrinterAction printAction4 = new SyncPrinterAction(new int[]{4,8,12,16}, false);
printAction1.setDependentAction(printAction4);
printAction2.setDependentAction(printAction1);
printAction3.setDependentAction(printAction2);
printAction4.setDependentAction(printAction3);
new Thread(printAction1, "T1").start();;
new Thread(printAction2, "T2").start();
new Thread(printAction3, "T3").start();
new Thread(printAction4, "T4").start();
}
}
class SyncPrinterAction implements Runnable {
private volatile boolean dependent;
private SyncPrinterAction dependentAction;
int[] data;
public void setDependentAction(SyncPrinterAction dependentAction){
this.dependentAction = dependentAction;
}
public SyncPrinterAction( int[] data, boolean dependent) {
this.data = data;
this.dependent = dependent;
}
public SyncPrinterAction( int[] data, SyncPrinterAction dependentAction, boolean dependent) {
this.dependentAction = dependentAction;
this.data = data;
this.dependent = dependent;
}
@Override
public void run() {
synchronized (this) {
for (int value : data) {
try {
while(dependentAction.isDependent())
//System.out.println("\t\t"+Thread.currentThread().getName() + " :: Waithing for dependent action to complete");
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
dependentAction.setDependent(true);
System.out.println(Thread.currentThread().getName() + " :: " +value);
dependent = false;
}
}
}
private void setDependent(boolean dependent) {
this.dependent = dependent;
}
private boolean isDependent() {
return dependent;
}
}
答案 14 :(得分:0)
在使用时尝试以下代码,您可以以这种方式运行n个线程。
image0.gif image1.gif
答案 15 :(得分: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();
}
答案 16 :(得分: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()
实施留作练习,所以下次你做对了!