java并发包的类_Java并发包中常用类小结(三) (转载)

转载地址:http://yhjhappy234.blog.163.com/blog/static/31632832201232410512971/

9、Semaphore

Semaphore是并发包中用于控制某个资源访问个数的类,例如数据库的连接池,我们用代码来演示一下一个连接池的实现:

packagecom.yhj.container.concurrent;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.Random;

importjava.util.concurrent.BlockingQueue;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

importjava.util.concurrent.LinkedBlockingQueue;

importjava.util.concurrent.Semaphore;

importjava.util.concurrent.TimeUnit;

/**

* @Described:基于信号量的测试用例

* @authorYHJ create at 2012-4-16 下午05:04:53

* @FileNmaecom.yhj.container.concurrent.SemaphoreTestCase.java

*/

publicclassSemaphoreTestCase {

//连接池

abstractclassPool{

protectedInteger maxActiveConnectionNum;

protectedInteger currentActiveConnectionNum;

protectedInteger maxWaitTime;

protectedList pools_used;

protectedBlockingQueue pools_free;

//构造器

protectedPool(Integer maxActiveConnectionNum,Integer currentActiveConnectionNum, Integer maxWaitTime) {

this.maxActiveConnectionNum= maxActiveConnectionNum;

this.currentActiveConnectionNum= currentActiveConnectionNum;

this.maxWaitTime= maxWaitTime;

this.pools_free= newLinkedBlockingQueue(maxActiveConnectionNum);

this.pools_used= newArrayList(maxActiveConnectionNum);

init();//直接创建最大的容量 本示例未做初始化不足扩容处理

}

privatevoidinit(){

for(inti=0;i

pools_free.add(newConnection());

}

//获取连接

publicabstractConnection getConnection();

//关闭连接

publicabstractvoidcloseConnection(Connection connection);

}

//连接供体

classConnection{

publicConnection() {System.out.println("创建了新的Connection : "+this);}

}

//普通连接池实现方案

classNormalPool extendsPool{

protectedNormalPool(Integer maxActiveConnectionNum,Integer currentActiveConnectionNum, Integer maxWaitTime) {

super(maxActiveConnectionNum, currentActiveConnectionNum, maxWaitTime);

}

@Override

publicConnection getConnection() {

Connection connection = null;

synchronized(pools_free) {

try{

//case 1# init

connection = pools_free.poll(maxWaitTime, TimeUnit.MILLISECONDS);

//case 2# init

//for(int i=0;i

//  connection = pools_free.poll();

//  if(null!=connection) break;

//  wait(1);//防止过度消耗CPU

//}

//以下为case1和case2共同的部分 建议选用case1 精度级别为纳秒case2的精度级别 毫秒

//long waitTime = maxWaitTime - (System.currentTimeMillis()-beginTime);

//wait(waitTime);

if(null==connection)

thrownewRuntimeException("Connection timepit with "+maxWaitTime+" milliseconds");

else{

pools_used.add(connection);

System.out.println(Thread.currentThread().getName()+"获取连接"+connection);

returnconnection;

}

} catch(Exception e) {

thrownewRuntimeException(e);

}

}

}

@Override

publicvoidcloseConnection(Connection connection){

synchronized(pools_used) {

if(pools_used.remove(connection)){

pools_free.add(connection);

}

System.out.println(Thread.currentThread().getName()+"释放连接"+connection);

connection = null;

}

}

}

//基于信号量的连接池

classSemaphorePool extendsPool{

privateSemaphore semaphore;

protectedSemaphorePool(Integer maxActiveConnectionNum,Integer currentActiveConnectionNum, Integer maxWaitTime) {

super(maxActiveConnectionNum, currentActiveConnectionNum, maxWaitTime);

semaphore= newSemaphore(maxActiveConnectionNum, true);

}

@Override

publicConnection getConnection() {

Connection connection = null;

try{

if(semaphore.tryAcquire(maxWaitTime,TimeUnit.MILLISECONDS)){

synchronized(pools_free) {

connection = pools_free.poll();

if(null== connection)

thrownewRuntimeException("NullPointException in connection free pools");

pools_used.add(connection);

System.out.println(Thread.currentThread().getName()+"获取连接"+connection);

returnconnection;

}

}else{

thrownewRuntimeException("Connection timepit with "+maxWaitTime+" milliseconds");

}

} catch(InterruptedException e) {

thrownewRuntimeException(e);

}

}

@Override

publicvoidcloseConnection(Connection connection) {

synchronized(pools_used) {

if(pools_used.remove(connection)){

pools_free.add(connection);

}

semaphore.release();

System.out.println(Thread.currentThread().getName()+"释放连接"+connection);

connection = null;

}

}

}

//待执行的任务

classTask implementsRunnable{

privateRandom random= newRandom();

privatePool pool;

publicTask(Pool pool) {

this.pool= pool;

}

@Override

publicvoidrun() {

try{

Connection connection = pool.getConnection();

Thread.sleep(random.nextInt(1000));

pool.closeConnection(connection);

} catch(InterruptedException e) {

}

}

}

//启动函数

publicvoidstart(){

intthredCount = 100;

Pool pool = newNormalPool(10, 10, 100);

ExecutorService service = Executors.newCachedThreadPool();

for(inti=0;i

service.execute(newTask(pool));

}

service.shutdown();

pool = newSemaphorePool(10, 10, 100);

service = Executors.newCachedThreadPool();

for(inti=0;i

service.execute(newTask(pool));

}

service.shutdown();

}

publicstaticvoidmain(String[] args) {

newSemaphoreTestCase().start();

}

}

运行程序,我们发现如下结果:

1344324488787534325.jpg

很显然,

pool-1-thread是第一个线程池的数据,县创建对应的DB连接,然后有很多线程来回去这些连接,随后线程池2进行和创建和分配操作。但是很显然,100ms的超时时间不能承载1~1000ms之间的线程等待,显然中间会产生超时的问题,如下图所示:

1287748018468698010.jpg

同时我们看到中间有连接释放和连接获取的过程。但是拉到最后我们可以看到,

pool-2很早就完成了,但是pool1还在执行,如下图所示

2585910611058244053.jpg

CountDownLatch

、CyclicBarrier我们在上面的例子中也用到了,分别被用在多线程下做计数器和集合点(其实是另一种计数器),用户控制多线程下的并发操作。而在并罚中还会经常用到的一个锁是ReentrantLock和ReentrantReadWriteLock。我们分别来看一下:

packagecom.yhj.container.concurrent;

importjava.util.HashMap;

importjava.util.Map;

importjava.util.concurrent.CountDownLatch;

importjava.util.concurrent.CyclicBarrier;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

importjava.util.concurrent.locks.Lock;

importjava.util.concurrent.locks.ReentrantLock;

importjava.util.concurrent.locks.ReentrantReadWriteLock;

/**

* @Described:读写分离的互斥锁 测试用例

* @authorYHJ create at 2012-4-23 下午09:22:53

* @FileNmaecom.yhj.container.concurrent.ReentrantReedWriteLockTestCase.java

*/

publicclassReentrantReadWriteLockTestCase {

privateMap map= newHashMap();

privateCountDownLatch latch;//计数器

privateCyclicBarrier barrier;//集合点

//任务

abstractclassTask implementsRunnable{

protectedLock lock;

publicTask(Lock lock) {this.lock= lock;}

@Override

publicvoidrun() {

try{

barrier.await();//到达集合点之前 等待

} catch(Exception e) {

e.printStackTrace();

}

try{

lock.lock(); //锁数据

process();

Thread.sleep(100);//等待100ms

} catch(Exception e) {

e.printStackTrace();

} finally{

lock.unlock();//解锁

latch.countDown();

}

}

//真正的业务

abstractprotectedvoidprocess();

}

//读任务

classReadTask extendsTask{

publicReadTask(Lock lock) {super(lock);}

@Override

protectedvoidprocess() {

map.get("test");

}

}

//读任务

classWriteTask extendsTask{

publicWriteTask(Lock lock) {super(lock);}

@Override

protectedvoidprocess() {

map.put("test", "case");

}

}

//初始化

privatevoidinit(intthredCount){

latch= newCountDownLatch(thredCount);

barrier= newCyclicBarrier(thredCount);

}

//计算耗时

privatevoidcalculateTimeCost(longbeginTime){

try{

latch.await();

System.out.println("total time cost "+(System.currentTimeMillis()-beginTime)+" ms");

} catch(InterruptedException e) {

e.printStackTrace();

}

}

//启动函数

publicvoidstart(){

intwriteThredCount = 100,readThredCount = 400;

ExecutorService service = Executors.newCachedThreadPool();

//计算使用ReentrantReadWriteLock耗时

init(writeThredCount+readThredCount);

ReentrantReadWriteLock reentrantReadWriteLock = newReentrantReadWriteLock();

longbeginTime = System.currentTimeMillis();

for(inti=0;i

service.execute(newWriteTask(reentrantReadWriteLock.writeLock()));

for(inti=0;i

service.execute(newReadTask(reentrantReadWriteLock.readLock()));

calculateTimeCost(beginTime);

//计算使用ReentrantLock的耗时

init(writeThredCount+readThredCount);

ReentrantLock reentrantLock = newReentrantLock();

beginTime = System.currentTimeMillis();

for(inti=0;i

service.execute(newWriteTask(reentrantLock));

for(inti=0;i

service.execute(newReadTask(reentrantLock));

calculateTimeCost(beginTime);

service.shutdownNow();

}

//主函数

publicstaticvoidmain(String[] args) {

newReentrantReadWriteLockTestCase().start();

}

}

我们很清楚的看到,在并发情况下,读写锁分离明显优于一把锁。尤其是在读多写少的环境。

Condition。

Condition主要用于控制锁在并发下的唤醒和等待操作,其API说明如下:

596726950644037851.jpg

以下是官方的一个示例代码,如下所示:

classBoundedBuffer {

finalLock lock= newReentrantLock();

finalCondition notFull= lock.newCondition();

finalCondition notEmpty= lock.newCondition();

finalObject[] items= newObject[100];

intputptr, takeptr, count;

publicvoidput(Object x) throwsInterruptedException {

lock.lock();

try{

while(count== items.length)

notFull.await();

items[putptr] = x;

if(++putptr== items.length) putptr= 0;

++count;

notEmpty.signal();

} finally{

lock.unlock();

}

}

publicObject take() throwsInterruptedException {

lock.lock();

try{

while(count== 0)

notEmpty.await();

Object x = items[takeptr];

if(++takeptr== items.length) takeptr= 0;

--count;

notFull.signal();

returnx;

} finally{

lock.unlock();

}

}

}

以上便是我们实际中可能经常要用到的一些并发包的类,由于时间和精力的原因,在这里也没写那么的详细,当然更多的还是实践,只有实践多了,我们才能更熟练的掌握这些并发相关的知识!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值