H2O与Java线程同步

时间:2023-03-08 22:23:54

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.****.net/vernonzheng/article/details/8288251 http://blog.****.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();
}
}
}