线程同步 – 如何交替执行线程

我一直在尝试使用wait()和notify()来解决涉及线程通信的问题。 基本上我有2个线程T1和T2,我希望它们按以下顺序执行

T1,T2,T1,T2 ……我怎样才能做到这一点?

实际问题:有2个线程T1 – 打印奇数(比如1 – 100)和T2 – 打印偶数(1 – 100)。 现在,输出应该是1,2,3,4,5 …… 100

您描述了生产者 – 消费者模式。

它是在许多Java书籍中描述的java实现,包括M.Grand“Patterns in Java。Volume I”和Naughton and Schildt的“Java 2:The Complete Reference”。

基本思想:两个线程都应该使用1个监视器(即它们的代码应该在synchronized(monitor) {}块内)。 您还需要一些标志变量,它应该指示当前两个线程中的哪一个应该工作。

当你的一个线程在同步块内时,它应该检查标志变量是否轮到他完成这项工作。 如果是,请让它工作,然后更改标志值,然后通知所有等待的线程。 如果不是,那么它应该等待。

查看java.util.concurrent包,特别是Exchanger

您正在尝试并行化多步流程吗? 如果是这样,请在此处查看我的答案,以获取方法和一些工作代码。 答案涉及ExecutorService (或两个)和一个或多个工作队列。

对于这种方法,您的处理需要能够适合Runnable以及处理的中间状态信息。 您将每个步骤作为RunnableExecutorService ,它将添加第二个Runnable以执行下一步。 这样可以保持执行顺序,但可以让您有效地并行运行多个线程。

:编辑:

正如另一个人所建议的那样,如果您明确希望将处理限制为2个线程,则可以使用Exchanger库类。 我更喜欢上述方法,因为它维护了执行顺序,并允许您完全使用现代的4核(和8核)系统。 它还应该减少同步。

如果T1和T2是Runnable接口的2个不同实现,T1是一个只打印奇数(1,3,…)的线程,T2是打印偶数(1,2 …..)的一个,这可以通过在共享监视器上使用wait()和notify()方法来完成。 重要的是每个线程在打印其值之前检查共享标志。 以下代码有效;

 //The shared monitor public class Mutex { public static boolean oddFlag; } //The Thread that is supposed to print Odd numbers (assuming an upper limit of 99) public class OddPrinter implements Runnable { private Mutex mutex; public OddPrinter(Mutex mutex) { this.mutex = mutex; } public synchronized void run() { System.out.println("Started Thread: OddPrinter"); int i; for(i=1; i<100; i+=2 ) { synchronized (mutex) { while(!Mutex.oddFlag) { try { mutex.wait(); } catch (InterruptedException ie) { Thread.currentThread().interrupted(); } } if(Mutex.oddFlag == true) { System.out.println("Print from OddPrinter: "+i); Mutex.oddFlag = false; mutex.notify(); } } } System.out.println("Finished Thread: OddPrinter: "+i); } } //The Thread that is supposed to print Odd numbers (assuming an upper limit of 98) public class EvenPrinter implements Runnable { private Mutex mutex; public EvenPrinter(Mutex mutex) { this.mutex = mutex; } public synchronized void run() { System.out.println("Started Thread: EvenPrinter"); int i; for(i=2; i<100; i+=2) { synchronized (mutex) { while(Mutex.oddFlag) { try { mutex.wait(); } catch (InterruptedException ie) { Thread.currentThread().interrupted(); } } if(!(Mutex.oddFlag == true)) { System.out.println("Print from EvenPrinter: "+i); Mutex.oddFlag = true; mutex.notify(); } } } System.out.println("Finished Thread: EvenPrinter: "+i); } } //The test harness that executes the threads import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class NumberPrinterTest { public static void main(String[] args) throws Exception{ ExecutorService es = Executors.newFixedThreadPool(2); Mutex mutex = new Mutex(); OddPrinter op = new OddPrinter(mutex); EvenPrinter ep = new EvenPrinter(mutex); Mutex.oddFlag = true; es.execute(op); es.execute(ep); if(null != es){ es.shutdown(); try { es.awaitTermination(1, TimeUnit.MINUTES); } catch (InterruptedException e) { Thread.currentThread().interrupted(); } } } }