首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 企业软件 > 行业软件 >

Java多线程(八)之Se地图hore、CountDownLatch、CyclicBarrier、Exchanger

2012-12-14 
Java多线程(八)之Semaphore、CountDownLatch、CyclicBarrier、Exchanger一、引言Semaphore:一个计数信号量Coun

Java多线程(八)之Semaphore、CountDownLatch、CyclicBarrier、Exchanger
一、引言
Semaphore               :一个计数信号量CountDownLatch          :一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 CyclicBarrier           :一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点    Exchanger               :方便了两个共同操作线程之间的双向交换
二、Semaphore

Semaphore 是一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。

说白了,Semaphore是一个计数器,在计数器不为0的时候对线程就放行,一旦达到0,那么所有请求资源的新线程都会被阻塞,包括增加请求到许可的线程,也就是说Semaphore不是可重入的。每一次请求一个许可都会导致计数器减少1,同样每次释放一个许可都会导致计数器增加1,一旦达到了0,新的许可请求线程将被挂起。

缓存池整好使用此思想来实现的,比如链接池、对象池等。


计数信号可以用于限制有权对资源进行并发访问的线程数。该方法对于实现资源池或限制 Web 爬虫(Web crawler)中的输出 socket 连接非常有用。

清单1 对象池

class FillAndEmpty {   Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();   DataBuffer initialEmptyBuffer = new DataBuffer();   DataBuffer initialFullBuffer = new DataBuffer();   class FillingLoop implements Runnable {     public void run() {       DataBuffer currentBuffer = initialEmptyBuffer;       try {         while (currentBuffer != null) {           addToBuffer(currentBuffer);           if (currentBuffer.full())             currentBuffer = exchanger.exchange(currentBuffer);         }       } catch (InterruptedException ex) { ... handle ... }     }   }   class EmptyingLoop implements Runnable {     public void run() {       DataBuffer currentBuffer = initialFullBuffer;       try {         while (currentBuffer != null) {           takeFromBuffer(currentBuffer);           if (currentBuffer.empty())             currentBuffer = exchanger.exchange(currentBuffer);         }       } catch (InterruptedException ex) { ... handle ...}     }   }   void start() {     new Thread(new FillingLoop()).start();     new Thread(new EmptyingLoop()).start();   } }

JDK 6以后为了支持多线程多对象同时Exchanger了就进行了改造(为了支持更好的并发),采用ConcurrentHashMap的思想,将Stack分割成很多的片段(或者说插槽Slot),线程Id(Thread.getId())hash相同的落在同一个Slot上,这样在默认32个Slot上就有很好的吞吐量。当然会根据机器CPU内核的数量有一定的优化,有兴趣的可以去了解下Exchanger的源码。

Exchanger实现的是一种数据分片的思想,这在大数据情况下将数据分成一定的片段并且多线程执行的情况下有一定的使用价值。


参考:
java的concurrent用法详解http://blog.csdn.net/a511596982/article/details/8063742
Java多线程(七)之同步器基础:AQS框架深入分析
http://blog.csdn.net/a511596982/article/details/8275624
JDK 5.0 中的并发
http://www.ibm.com/developerworks/cn/education/java/j-concur/section5.html
关于 java.util.concurrent 您不知道的 5 件事,第 2 部分
http://www.ibm.com/developerworks/cn/java/j-5things5.html
深入浅出 Java Concurrency (10): 锁机制 part 5 闭锁 (CountDownLatch)
http://www.blogjava.net/xylz/archive/2010/07/09/325612.html
深入浅出 Java Concurrency (11): 锁机制 part 6 CyclicBarrier
http://www.blogjava.net/xylz/archive/2010/07/12/325913.html
深入浅出 Java Concurrency (12): 锁机制 part 7 信号量(Semaphore)
http://www.blogjava.net/xylz/archive/2010/07/13/326021.html深入浅出 Java Concurrency (26): 并发容器 part 11 Exchanger
http://www.blogjava.net/xylz/archive/2010/11/22/338733.html
Java线程学习笔记(十)CountDownLatch 和CyclicBarrier
http://www.iteye.com/topic/657295

热点排行