Java 5以前的线程同步采用syncronized和wait,notify,notifyAll来实现,比较粗糙。之后有了Lock和Condition。
ReentrantLock的简单lock,unlock相当于syncronized。而通过condition的signal和await,可以实现更细粒度的控制。
http://www.cnblogs.com/yaowukonga/archive/2012/08/27/2658329.html http://blog.csdn.net/vernonzheng/article/details/8288251 http://blog.csdn.net/fw0124/article/details/6672522
下面这个例子是本人的实现,望指正。基本意思是H函数会产生H分子,O函数产生O分子,每个线程产生一个分子,当有两个H一个O时,这三个线程退出。
实现思路是用Condition的Queue来存顺序,这样能够控制线程退出的顺序(也能够根据需求实现不同的顺序),而且能避免惊群。测试用例简单测试了当H和O不足和超出时的情形。
import java.util.*; import java.util.concurrent.locks.*; class H2O implements Runnable { static final Lock lock = new ReentrantLock(); static LinkedList<Condition> hQueue = new LinkedList<Condition>(); static LinkedList<Condition> oQueue = new LinkedList<Condition>(); private String particle; private int id; public H2O(String particle, int id) { this.particle = particle; this.id = id; } public void run() { if (particle.equals("h")) { H(id); } else if (particle.equals("o")) { O(id); } } public static void H(int hid) { lock.lock(); try { if (hQueue.size() >= 1 && oQueue.size() >= 1) { // generate water Condition hc = hQueue.poll(); Condition oc = oQueue.poll(); hc.signal(); oc.signal(); System.out.println("H:" + hid); } else { // wait Condition c = lock.newCondition(); hQueue.add(c); c.await(); System.out.println("H:" + hid); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { lock.unlock(); } } public static void O(int oid) { lock.lock(); try { if (hQueue.size() >= 2) { // generate water Condition hc1 = hQueue.poll(); Condition hc2 = hQueue.poll(); hc1.signal(); hc2.signal(); System.out.println("O:" + oid); } else { // wait Condition c = lock.newCondition(); oQueue.add(c); c.await(); System.out.println("O:" + oid); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { lock.unlock(); } } } public class Solution { public static void main(String args[]) throws InterruptedException { for (int i = 1; i <= 6; i++) { new Thread(new H2O("h", i)).start(); } Thread.sleep(1000); for (int i = 1; i <= 6; i++) { new Thread(new H2O("o", i)).start(); } Thread.sleep(1000); for (int i = 7; i <= 36; i++) { new Thread(new H2O("h", i)).start(); } Thread.sleep(1000); for (int i = 7; i <= 12; i++) { new Thread(new H2O("o", i)).start(); } Thread.sleep(1000); for (int i = 13; i <= 18; i++) { new Thread(new H2O("o", i)).start(); } } }