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

时间:2010-02-14 19:58:03

标签: java multithreading synchronization wait

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

T1,T2,T1,T2 .....我怎样才能实现这一目标?

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

4 个答案:

答案 0 :(得分:3)

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

这是java书中描述的java实现,包括M.Grand“Patterns in Java。第一卷”和“Java 2:完整参考”,作者是Naughton和Schildt。

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

<强>:编辑:

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

答案 3 :(得分:0)

如果T1和T2是Runnable接口的两个不同实现,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();
        }
    }

}

}