标签:
Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
//availablePermits()指的是当前信号灯库中有多少个可以被使用
System.out.println("-----------------" + semp.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
关于生产者和消费者
/**
* 仓库,用来存放产品
*
* @author 林计钦
* @version 1.0 2013-7-24 下午04:54:16
*/
public class Storage {
BlockingQueue<Product> queues = new LinkedBlockingQueue<Product>(10);主要是利用 这个阻塞队列来处理生产和消费。
信号变量
private Lock lock = new ReentrantLock(); // 账户锁
private Condition _save = lock.newCondition(); // 存款条件
private Condition _draw = lock.newCondition(); // 取款条件通过 _save.signalAll()
_save.await();
而在Java5中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。
主要这里,的lock实际上就是锁定到condition上面。
public void drawing(int x, String name) {
lock.lock(); // 获取锁
try {
if (cash - x < 0) {
_draw.await(); // 阻塞取款操作
} else {
cash -= x; // 取款
System.out.println(name + "取款" + x + ",当前余额为" + cash);
}
_save.signalAll(); // 唤醒所有存款操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 释放锁
}
} public void saving(int x, String name) {
lock.lock(); // 获取锁
if (x > 0) {
cash += x; // 存款
System.out.println(name + "存款" + x + ",当前余额为" + cash);
}
_draw.signalAll(); // 唤醒所有等待线程。
lock.unlock(); // 释放锁
}可以看到 lock不会造成死锁。
障碍器
CountDownLatchu是所有子程序执行完以后,再执行主线程。关注的是主线程。
CyclicBarrier是多有子线程都执行到某一点后,在继续执行。关注的是子线程。
CyclicBarrierTest test = new CyclicBarrierTest();
// 创建障碍器,并设置MainTask为所有定数量的线程都达到障碍点时候所要执行的任务(Runnable)
CyclicBarrier cb = new CyclicBarrier(7, test.new MainTask());
test.new SubTask("A", cb).start();
test.new SubTask("B", cb).start();
test.new SubTask("C", cb).start();
test.new SubTask("D", cb).start();
test.new SubTask("E", cb).start();
test.new SubTask("F", cb).start();
test.new SubTask("G", cb).start();就是让所有子线程 执行到了
// 通知障碍器已经完成
cb.await();然后才执行主线程。
这里是执行到了这个点,第一个是全部执行完毕。
这个可以用于 分表查询。
即所有的总数计算完毕,再执行主线程。
也可以通过join的方式,信号量,原子量方式。
还可以主线程中定时判断子线程执行结果。可以由线程队列,变量等得知具体情况。
还可以,主线程 await();
个人觉得还是join比较优雅。
标签:
原文地址:http://www.cnblogs.com/mophes/p/4451175.html