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

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

6、ThredPoolExecutor

ThredPoolExecutor是基于命令模式下的一个典型的线程池的实现,主要通过一些策略实现一个典型的线程池,目前已知的策略有ThreadPoolExecutor.AbortPolicy, ThreadPoolExecutor.CallerRunsPolicy, ThreadPoolExecutor.DiscardOldestPolicy, ThreadPoolExecutor.DiscardPolicy。废话不多说,我们来看一个示例:

packagecom.yhj.container.concurrent;

importjava.util.concurrent.ArrayBlockingQueue;

importjava.util.concurrent.BlockingQueue;

importjava.util.concurrent.CountDownLatch;

importjava.util.concurrent.CyclicBarrier;

importjava.util.concurrent.Executors;

importjava.util.concurrent.LinkedBlockingDeque;

importjava.util.concurrent.RejectedExecutionException;

importjava.util.concurrent.SynchronousQueue;

importjava.util.concurrent.ThreadPoolExecutor;

importjava.util.concurrent.TimeUnit;

importjava.util.concurrent.atomic.AtomicInteger;

/**

* @Described:线程池测试

* @authorYHJ create at 2012-4-13 下午01:34:03

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

*/

publicclassThreadPoolExecutorTestCase {

privateAtomicInteger successTask= newAtomicInteger(0);//成功的任务数目

privateAtomicInteger failedTask= newAtomicInteger(0);//失败的任务数目

privateInteger thredCount;//启动的线程数

privateThreadPoolExecutor executor;

privateCountDownLatch latch;//计数器

privateCyclicBarrier cyclicBarrier;//集合点

//构造函数

publicThreadPoolExecutorTestCase(BlockingQueue queue,Integer thredCount) {

super();

System.out.println("queue name:"+queue.getClass());

this.thredCount=thredCount;

executor= newThreadPoolExecutor(10, 500, 30, TimeUnit.SECONDS, queue, Executors.defaultThreadFactory(), newThreadPoolExecutor.AbortPolicy());

}

//要处理的任务列表

classTask implementsRunnable{

privateCountDownLatch latch;//计数器

privateCyclicBarrier cyclicBarrier;//集合点

publicTask(CountDownLatch latch, CyclicBarrier cyclicBarrier) {

super();

this.latch= latch;

this.cyclicBarrier= cyclicBarrier;

}

@Override

publicvoidrun() {

try{

cyclicBarrier.await();//到达预期集合点再执行

} catch(Exception e) {

e.printStackTrace();

}

try{

executor.execute(newRunnable() {

@Override

publicvoidrun() {

try{

Thread.sleep(3000);//休眠3秒

} catch(Exception e) {

e.printStackTrace();

}

latch.countDown();

successTask.incrementAndGet();

}

});

} catch(RejectedExecutionException e) {

latch.countDown();

failedTask.incrementAndGet();

}

}

}

//初始化

publicvoidinit(){

latch= newCountDownLatch(thredCount);

cyclicBarrier= newCyclicBarrier(thredCount);

}

//启动方法

publicvoidstart(){

longstartTime = System.currentTimeMillis();

for(inti=0;i

newThread(newTask(latch, cyclicBarrier)).start();

try{

latch.await();

executor.shutdownNow();

System.out.println("total time:"+(System.currentTimeMillis()-startTime));

System.out.println("success count:"+successTask.intValue());

System.out.println("failed count:"+failedTask.intValue());

System.out.println("===end===");

} catch(Exception e) {

e.printStackTrace();

}

}

//强制关闭方法

publicvoidshutDonw(){

executor.shutdownNow();

}

//主函数

publicstaticvoidmain(String[] args) {

//性能优先 速度优先

ThreadPoolExecutorTestCase testCase = newThreadPoolExecutorTestCase(newSynchronousQueue(), 1000);

testCase.init();

testCase.start();

//稳定优先使用数组缓存队列

testCase=newThreadPoolExecutorTestCase(newArrayBlockingQueue(10), 1000);

testCase.init();

testCase.start();

//稳定优先使用链表缓存队列

testCase=newThreadPoolExecutorTestCase(newLinkedBlockingDeque(10), 1000);

testCase.init();

testCase.start();

//关掉处理器

//testCase.shutDonw();

}

}

运行结果如下:

1572882169876406364.jpg

我们可以看到,通过缓冲可以提升成功率,但是明显消耗的时间大大增加了。

7、Executors

对于线程池,其实也是我们经常用的一个东西,在多线程环境下,线程池是控制并发操作的一个很好的解决方案,但是每次都通过ThredPoolExecutor未免有点麻烦,因此JDK为我们提供可Executors以便我们能轻松的创建ThredPoolExecutor的实例,我们来看以下有哪些快速创建实例的方法:

1577667244480670149.jpg

以上的方法估计也是大家经常用到的,具体的实例我在此也就不多写了。

8、FutureTask

FutureTask可以用户异步获取数据的一种方法,我们前面提到使用ConcurrentHashMap代替HashMap来提升map的性能,但是我们知道,ConcurrentHashMap在进行读操作的时候基本是不加锁的,假设我们有这么一个需求,我们有一个数据库的连接池,默认是不初始化的,在第一次用户用到的时候进行初始化操作。那我们该如何实现的呢?

packagecom.yhj.container.concurrent;

importjava.util.HashMap;

importjava.util.Map;

importjava.util.concurrent.Callable;

importjava.util.concurrent.ConcurrentHashMap;

importjava.util.concurrent.CountDownLatch;

importjava.util.concurrent.CyclicBarrier;

importjava.util.concurrent.FutureTask;

importjava.util.concurrent.locks.ReentrantLock;

/**

* @Described:异步通知测试用例

* @authorYHJ create at 2012-4-14 上午11:31:26

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

*/

publicclassFutureTaskTestCase {

//测试需求: 使用一个key-value 形式存储

//测试要求: 所有的连接池对象只能创建一次 且不能加载时初始化 在第一次访问时初始化目标连接池对象

//测试实现: 通过HashMap加锁实现和FutureTask实现

//Map测试任务 用例

interfaceMapTask{

//根据指定的key 获取指定的DB连接key etc:mysql sqlserver oracle DB2 and so on

publicConnection getConnection(String key);

}

//枚举 数据库类型

enumDB_TYPE{

MYSQL(),SQLSERVR,ORACLE,DB2;

}

//使用HashMap加锁实现

classHashMapWithLock implementsMapTask{

privateMap pools= newHashMap();

privateReentrantLock lock= newReentrantLock();

//加锁获取连接对象,防止高并发下数据重复创建

@Override

publicConnection getConnection(String key){

try{

lock.lock(); //锁定操作,后续再来等待

if(!pools.containsKey(key))

pools.put(key, newDBConnectionPool(key));

returnpools.get(key).getConnection();

} finally{

lock.unlock();//解锁操作

}

}

}

//使用ConcurrentHashMap实现,因为ConcurrentHashMap读取时不加锁,因此需要通过回调的方式控制并发

classConcurrentHashMapWithFutureTask implementsMapTask{

privateConcurrentHashMap> pools= newConcurrentHashMap>();

privateFutureTask futureTask;

//通过回调的方式 确保多线程下不会引发多次创建

@Override

publicConnection getConnection(finalString key){

try{

if(!pools.containsKey(key)){

Callable callable = newCallable() {

@Override

publicDBConnectionPool call() throwsException {

pools.put(key,futureTask);

returnnewDBConnectionPool(key);

}

};

FutureTask tmpTask = newFutureTask(callable);

futureTask= pools.putIfAbsent(key, tmpTask);

if(futureTask==null){

futureTask= tmpTask;

futureTask.run();

}

}

returnpools.get(key).get().getConnection();

} catch(Exception e) {

e.printStackTrace();

returnnull;

}

}

}

//DB连接池测试用例供体

classDBConnectionPool{

publicDBConnectionPool(String key) {

System.out.println("创建了"+key+"类型的数据库连接池");

}

//获取DB连接

publicConnection getConnection(){

// create Connection for db

returnnewConnection();

}

}

//DB连接 测试供体

classConnection{

}

//任务执行器 待执行的任务

classExecutorTask implementsRunnable{

privateCyclicBarrier barrier;//计数器

privateCountDownLatch latch;//集合点

privateMapTask task;//待执行的任务

privateString key;

publicExecutorTask(String key,CyclicBarrier barrier, CountDownLatch latch,MapTask task) {

this.barrier= barrier;

this.latch= latch;

this.task= task;

this.key=key;

}

@Override

publicvoidrun() {

try{

barrier.await();//到达集合点之前等待 确保数据是并发执行的

Connection connection = task.getConnection(key);

if(null==connection)

thrownewNullPointerException("Null Connection Exception with "+key);

latch.countDown();

} catch(Exception e) {

e.printStackTrace();

}

}

}

//执行函数

publicvoidexecute(String key,intthredCount,MapTask task){

CyclicBarrier barrier = newCyclicBarrier(thredCount);

CountDownLatch latch = newCountDownLatch(thredCount);

longbeginTime = System.currentTimeMillis();

System.out.println("===start "+task.getClass()+"===");

for(inti=0;i

newThread(newExecutorTask(key, barrier, latch, task)).start();

}

try{

latch.await();

System.out.println("====end "+task.getClass()+" still time "+(System.currentTimeMillis()-beginTime)+"===");

} catch(InterruptedException e1) {

thrownewRuntimeException(e1);

}

}

//启动函数

publicvoidstart(){

intthredCount = 200;

MapTask hashMapWithLock = newHashMapWithLock();

MapTask concurrentHashMapWithFutureTask = newConcurrentHashMapWithFutureTask();

execute("mysql",thredCount, hashMapWithLock);

execute("sqlserver",thredCount, concurrentHashMapWithFutureTask);

}

//主函数

publicstaticvoidmain(String[] args) {

//启动主进程

newFutureTaskTestCase().start();

//等待所有进程结束

while(Thread.activeCount()>1){

Thread.yield();

}

}

}

执行结果如下:

3099039493601763805.jpg

我们看到对象值创建了一次,但是通过回调的方式速度会慢一点,毕竟是异步的,有一部分线程需要等待,但是在多线程的模式下,显然我们可以规避单点访问堆积过大的问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值