我一直在尝试使用 wait() 和 notify() 解决涉及线程通信的问题。基本上我有 2 个线程 T1 和 T2,我希望它们按以下顺序执行
T1,T2,T1,T2 .....我怎样才能做到这一点?
实际问题:有 2 个线程 T1 - 打印奇数(例如 1 - 100)和 T2 - 打印偶数(1 - 100)。现在,输出应该是 1, 2, 3, 4 , 5 , .... 100
我一直在尝试使用 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 “Java 中的模式。第 I 卷”和 Naughton 和 Schildt 的“Java 2:完整参考”。
基本思想:两个线程都应该使用 1 个监视器(即它们的代码应该在synchronized(monitor) {}
块内)。您还需要一些标志变量,该变量应该指示两个线程中的哪一个当前应该工作。
当您的一个线程在同步块内时,它应该检查标志变量是否轮到他做这项工作。如果是,让它工作,然后更改标志值,然后通知所有等待线程。如果没有,那么它应该等待。
查看 java.util.concurrent 包,特别是Exchanger
您正在尝试并行化多步骤过程,对吗?如果是这样,请在此处查看我的答案以获取方法和一些工作代码来做到这一点。答案涉及一个ExecutorService
(或两个)和一个或多个工作队列。
对于这种方法,您的处理需要能够适应 Runnable,以及用于处理的中间状态信息。 您将每个步骤ExecutorService
作为 a 提供给Runnable
,这将添加第二个 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();
}
}
}
}