ExecutorService并发池的应用

来源:互联网 发布:淘宝大学紫米教育骗 编辑:程序博客网 时间:2024/05/22 02:20

同样还是工作中用到的ExecutorService这个线程池。

多线程这块一直在我印象里就是一个难缠的家伙。自己本来也是新手

还用了ExecutorService这个类,所以不用想,给我带来了很大的麻烦。ExecutorService这个从API查得好像有三种模式。具体的

我也就不多少有什么区别了,因为我也搞不清。最终我选择了Executors.newFixedThreadPool(10); 这个是生成一个固定线程数

的线程池,在这里我就定义了一个只能容纳10个线程的线程池。

那么定义好了怎么用呢,看看代码吧:

int pageDownloaderPoolNumber =10;

public static ExecutorService pageDownloaderPool = Executors.newFixedThreadPool(pageDownloaderPoolNumber);

首先定义好pageDownloaderPool,最大线程数为10。

crawlerFactory cf = new crawlerFactory(crawler); // 此处为new一个线程对象,因为在线程池中放的任务必须是一个线程类的对象

即继承了Runnable接口或其他某某的类的对象。

pageFutureList.add(pageDownloaderPool.submit(cf));//此处是将线程任务放进线程池中执行。注意,因为该线程池可以返回

一个任务队列。所以我们要定义一个FutureList来获得这些任务队列:

public static List<Future> pageFutureList = new ArrayList<Future>(pageDownloaderPoolNumber);

这样线程池里的任务就启动了,但要记住,如果你有30个线程同时启动,那么最多有10个在工作,同时还得对任务队列进行管理

特别是pageFutureList.add(pageDownloaderPool.submit(cf));这个在循环中的话一定要加上控制:

while(){

----------

hasFreeThread(pageFutureList);

if(pageFutureList.size() < pageDownloaderPoolNumber){

     pageFutureList.add(pageDownloaderPool.submit(cf));

 

}

 

同时有这么一个方法去检测队列是否有空闲的:

public static boolean hasFreeThread(List<Future> list){
        synchronized (list) {
            if(list.size() == 0){
                return true;
            }
            Future finishedFuture = null;
            try{
                for (Future temp : list) {
                    if(temp.isDone()/* || temp.get() == null*/){
                        finishedFuture = temp;
                        return true;
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
                return false;
            }finally{
                if(finishedFuture != null){
                    list.remove(finishedFuture);
                }
            }
            return false;
        }
    }

这样的话任务队列中就保持着永远最大数是10,当完成一个任务变成9后,下次就再加入一个任何到队列,就避免了线程的阻塞