如何确保Java线程以特定顺序运行

给定三个线程,1-3,打印一个字母,AC,我该如何保证输出顺序?

我想线程的输出是“ABCABCABC”

线程独立运行,因此除非您特别努力同步线程,否则永远不会获得此类输出。 预期独立运行的3个线程将打印“随机”输出,因为它可以由OS来调度线程。

这可能不是线程应该做的,但是,它可以通过简单地使用join来实现(它要求启动ING线程等待启动ED线程的完成。

class A implements Runnable { @Override public void run() { try { Thread.sleep(12); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ClassA : A"); } } class B implements Runnable { @Override public void run() { try { Thread.sleep(12); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ClassB : B"); } } class C implements Runnable { @Override public void run() { try { Thread.sleep(12); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ClassC : C"); } } public class OrderedThreadApp { public static void main(String[] args) { Thread a = new Thread(new A()); Thread b = new Thread(new B()); Thread c = new Thread(new C()); a.start(); try { a.join(); b.start(); b.join(); c.start(); } catch (InterruptedException e) { e.printStackTrace(); } } } 

检查CyclicBarrier ,这可能对您有所帮助。

您可以通过组合CountDownLatchCyclicBarrier来实现此目的。 以下是示例代码:

  package org.orange.didxga; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; public class ThreadExecutionOrder { private CountDownLatch countDownLatch = new CountDownLatch(2); private CountDownLatch countDownLatch1 = new CountDownLatch(1); private CyclicBarrier barrier; private final Object monitor = new Object(); public static void main(String[] args) { // TODO Auto-generated method stub new ThreadExecutionOrder().test(); } public void test() { Runnable t1 = new Runnable() { @Override public void run() { System.out.print("A"); countDownLatch1.countDown(); countDownLatch.countDown(); try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }; Runnable t2 = new Runnable() { @Override public void run() { try { countDownLatch1.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("B"); countDownLatch.countDown(); try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }; Runnable t3 = new Runnable() { @Override public void run() { try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("C"); try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }; for(int i=0; i<3; i++) { barrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { synchronized (monitor) { countDownLatch = new CountDownLatch(2); countDownLatch1 = new CountDownLatch(1); monitor.notify(); } } }); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); synchronized (monitor) { try { monitor.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } 

您可以使用wait和notify进行线程间通信。 我在这里使用turn int变量来表示线程之间的信号。

 public class ThreadInterleaving{ public static void main(String[] args){ MyThread h = new MyThread(); Thread t1 = new Thread(h); Thread t2 = new Thread(h); Thread t3 = new Thread(h); t1.start(); t2.start(); t3.start(); } } class MyThread implements Runnable{ public static int turn; @Override public void run(){ for(int i =0;i<3;i++){ synchronized(this){ if(turn == 0){ System.out.println("Thread1"); turn =1 ; notify(); }else{ try{ wait(); }catch(InterruptedException ie){ } } if(turn == 1){ System.out.println("Thread2"); turn = 2; notify(); }else{ try{ wait(); }catch(InterruptedException ie){ } } if(turn == 2){ System.out.println("Thread3"); System.out.println("*********"); turn = 0; notify(); }else{ try{ wait(); }catch(InterruptedException ie){ } } } } } } /*Output Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* Thread1 Thread2 Thread3 ********* */ 

我在这里的解决方案: https : //gist.github.com/sinujohn/5fa717dfff680634c6b0c2a7eca108ac可以修改来实现这一目标。 我们的想法是创建一个保存状态的对象,并在所有线程中共享该对象。 只有一个同步块可以访问共享状态对象。

 public class Main { public static void main(String[] args) throws InterruptedException { MyState state = new MyState(); final Thread t1 = new Thread(new MyRunnable(10, 'A', state)); final Thread t2 = new Thread(new MyRunnable(10, 'B', state)); final Thread t3 = new Thread(new MyRunnable(10, 'C', state)); t1.start(); t2.start(); t3.start(); } } class MyState { private char state = 'A'; public char getState() { return state; } public void incrState() { switch(state) { case 'A': state = 'B'; return; case 'B': state = 'C'; return; default: state = 'A'; } } } class MyRunnable implements Runnable { private final int max; private final char value; private final MyState state; MyRunnable(int max, char value, MyState state) { this.max = max; this.value = value; this.state = state; } @Override public void run() { int count = 0; while(count < max) { synchronized (this.state) { if (this.state.getState() == this.value) { System.out.print(value); count++; this.state.incrState(); } } } } } 
 public class ThreadOrderTest { int status = 1; public static void main(String[] args) { ThreadOrderTest threadOrderTest = new ThreadOrderTest(); A a = new A(threadOrderTest); B b = new B(threadOrderTest); C c = new C(threadOrderTest); a.start(); b.start(); c.start(); } } class A extends Thread { ThreadOrderTest threadOrderTest; A(ThreadOrderTest threadOrderTest) { this.threadOrderTest = threadOrderTest; } @Override public void run() { try { synchronized (threadOrderTest) { for (int i = 0; i < 10; i++) { while (threadOrderTest.status != 1) { threadOrderTest.wait(); } System.out.print("A "); threadOrderTest.status = 2; threadOrderTest.notifyAll(); } } } catch (Exception e) { System.out.println("Exception 1 :" + e.getMessage()); } } } class B extends Thread { ThreadOrderTest threadOrderTest; B(ThreadOrderTest threadOrderTest) { this.threadOrderTest = threadOrderTest; } @Override public void run() { try { synchronized (threadOrderTest) { for (int i = 0; i < 10; i++) { while (threadOrderTest.status != 2) { threadOrderTest.wait(); } System.out.print("B "); threadOrderTest.status = 3; threadOrderTest.notifyAll(); } } } catch (Exception e) { System.out.println("Exception 2 :" + e.getMessage()); } } } class C extends Thread { ThreadOrderTest threadOrderTest; C(ThreadOrderTest threadOrderTest) { this.threadOrderTest = threadOrderTest; } @Override public void run() { try { synchronized (threadOrderTest) { for (int i = 0; i < 10; i++) { while (threadOrderTest.status != 3) { threadOrderTest.wait(); } System.out.println("C "); threadOrderTest.status = 1; threadOrderTest.notifyAll(); } } } catch (Exception e) { System.out.println("Exception 3 :" + e.getMessage()); } } } 

ExecutorService的

一个Executor,提供管理终止的方法和可以生成Future的方法,用于跟踪一个或多个异步任务的进度。

可以关闭ExecutorService,这将导致它拒绝新任务。 提供了两种不同的方法来关闭ExecutorService。 shutdown()方法将允许先前提交的任务在终止之前执行,而shutdownNow()方法则阻止等待任务启动并尝试停止当前正在执行的任务。 终止时,执行程序没有正在执行的任务,没有等待执行的任务,也没有任何新任务可以提交。 应关闭未使用的ExecutorService以允许回收其资源。

方法submit通过创建并返回可用于取消执行和/或等待完成的Future来扩展基本方法Executor.execute(java.lang.Runnable)。 方法invokeAny和invokeAll执行最常用的批量执行forms,执行一组任务,然后等待至少一个或全部完成。 (类ExecutorCompletionService可用于编写这些方法的自定义变体。)

Executors类为此包中提供的执行程序服务提供工厂方法。