mairongchao / Learning-Summary

0 stars 0 forks source link

线程池高并发使用 #1

Open mairongchao opened 7 years ago

mairongchao commented 7 years ago

1.我直接上代码

// 创建当前线程池
ExecutorService pool = Executors.newCachedThreadPool();
List<ServiceCallable> callers = new ArrayList<ServiceCallable>();
for(Entry<String, Object> entry : params.entrySet()){
    callers.add(new ServiceCallable(entry.getKey(), entry.getValue(), InvokeContext.get()));
}

List<Future<Map<String, String>>> results = pool.invokeAll(callers);
Map<String, String> result = new HashMap<String, String>();
for(Future<Map<String, String>> future : results){
    result.putAll(future.get());
}

上面代码有个问题就是,每次方法调用这里的话,都会创建一个新的线程池。
这些就没有完全利用到线程池的机制。如果当前调用两个线程池线程时,线程池没有new的话,
就会new出这两条线程,当调用完毕后,就会将该两条线程置于空闲(实际上是系统加上标志位),
当其它人再调用这两条线程的时候,线程池就不会再去new 这两条线程,而是把这两个空闲的线程给了它。
有一点是当两个方法同时调用这两条线程时,线程池就会生成4条这样的线程,调用完原理同上
单个方法调用 两个线程
|------------------------线程1--调用完就置于空闲,待分配给其它人用
|------------------------线程2--调用完就置于空闲,待分配给其它人用
---|
|
|
两个方法同时调用两个线程
|------------------------线程1--调用完就置于空闲,待分配给其它人用
|------------------------线程2--调用完就置于空闲,待分配给其它人用
---|------------------------线程1--调用完就置于空闲,待分配给其它人用
|------------------------线程2--调用完就置于空闲,待分配给其它人用
|
|

所以上面代码应该将线程池改成单例,这样利用线程池的缓存机制可以大大提高线程的并发能力。

//将ExecutorService pool 提升到当前类的私有变量,当有方法调有当前方法才初始化(加锁,防止多次初始化),<br/>
if(pool == null){
            synchronized(ServiceUtils.class){
                pool = Executors.newCachedThreadPool();
            }
        }
        List<ServiceCallable> callers = new ArrayList<ServiceCallable>();

        for(Entry<String, Object> entry : params.entrySet()){
            callers.add(new ServiceCallable(entry.getKey(), entry.getValue(), InvokeContext.get()));
        }

        List<Future<Map<String, String>>> results = pool.invokeAll(callers);
        Map<String, String> result = new HashMap<String, String>();
        for(Future<Map<String, String>> future : results){
            result.putAll(future.get());
        }
        return result;


由上面可以看出,学习应该注重学习原理,仅仅改变变量的初始化方法,就带来了并发性能极大的提升。