码迷,mamicode.com
首页 > 编程语言 > 详细

[笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池

时间:2015-08-25 23:54:12      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:java   线程池   并发   实战   

[笔记][Java7并发编程实战手册]系列目录


简介

newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,在需要时使用提供的 ThreadFactory 创建新线程。

newCachedThreadPool()创建的线程池的特性是:自动回收不使用的线程(终止并从缓存中移除那些已有 60 秒钟未被使用的线程),(在无可用线程的情况下)自动的为新来的task创建新线程。
正是因为这种特性,在小任务量,任务时间执行短的场景下能提高性能。然后如果在大量任务,且任务执行之间较长的场景中,系统将会超负荷。性能极低。

newFixedThreadPool(int nThreads) 就是来解决以上问题的。它创建一个固定大小的线程池,如果task任务数量大于nThreads数量,那么这些任务将在队列中排队,直到有可用线程再执行。

讲了2章了,可能有得人还不知道为什么要强转成ThreadPoolExecutor,可以看下面的源码,和下面的类图就明白了

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

技术分享


newSingleThreadExecutor:
  只创建一个线程的线程池。多余的task将以无界队列来运行。也就是阻塞到有可用线程才能运行。


示例

创建固定大小的线程池

场景描述:下面示例讲的是:创建一个固定大小的线程执行器线程池,然后循环创建几个task任务执行。观察线程数量和名称。

/**
 * Created by zhuqiang on 2015/8/25 0025.
 */
public class Client {
    public static void main(String[] args) {
        ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
//        es.shutdown();   // 如果先关闭再执行任务,则会拒绝执行任务,抛出RejectedExecutionException异常
        for (int i = 0; i < 10 ; i++) {
            es.execute(new Task(es,"task-"+i));
        }
        es.shutdown();

    }
}
class Task implements  Runnable{
    private  ThreadPoolExecutor es;
    private  String name;

    public Task(ThreadPoolExecutor es, String name) {
        this.es = es;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            long timeout = (long) (Math.random() * 10);
            TimeUnit.SECONDS.sleep(timeout);
            System.out.println(Thread.currentThread().getName() + "...执行完成..task=" + name +"    耗时:" + timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

某一次的运行结果:

pool-1-thread-2...执行完成..task=task-1    耗时:0
pool-1-thread-1...执行完成..task=task-0    耗时:3
pool-1-thread-3...执行完成..task=task-2    耗时:4
pool-1-thread-2...执行完成..task=task-3    耗时:5
pool-1-thread-1...执行完成..task=task-4    耗时:5
pool-1-thread-3...执行完成..task=task-5    耗时:7
pool-1-thread-3...执行完成..task=task-8    耗时:0
pool-1-thread-2...执行完成..task=task-6    耗时:8
pool-1-thread-1...执行完成..task=task-7    耗时:7
pool-1-thread-3...执行完成..task=task-9    耗时:8

结果说明:可以看到,创建了3个数量的线程池,在执行中,也只会使用这三个线程数量,而其他的则会阻塞等待执行。


创建固定大小的线程池的时候使用ThreadFactory

ThreadFactory的作用:构造一个新 Thread。实现也可能初始化属性、名称、守护程序状态、ThreadGroup 等等。

在写demo的时候,我认为最麻烦的就是,设置循环中创建的线程的join方法。 在没有使用线程池的时候,在循环中调用这个方法都麻烦,要么抛出异常,要么就只有再循环一次来单独设置。 就这个场景而言,使用ThreadFactory来就很简单了。 ——————– 好把,我以为在工厂中,自己调用join方法能行。但是测试过了。视乎没有效果。 那就只能看下用法。场景用途我暂时也不知道了

示例如下:

/**
 * Created by zhuqiang on 2015/8/25 0025.
 */
public class Client {
    public static void main(String[] args) {
//        ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);  //1 该注释代码。和下面为使用工厂的对比。
        ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newFixedThreadPool(3, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("xxxx" + thread.getId());  //对新创建的线程做一些操作
                return thread;
            }
        });
        for (int i = 0; i < 10 ; i++) {
            es.execute(new Task(es,"task-"+i));
        }
        es.shutdown();
    }
}
class Task implements  Runnable{
    private  ThreadPoolExecutor es;
    private  String name;

    public Task(ThreadPoolExecutor es, String name) {
        this.es = es;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            long timeout = (long) (Math.random() * 10);
            TimeUnit.SECONDS.sleep(timeout);
            System.out.println(Thread.currentThread().getName() + "...执行完成..task=" + name +"    耗时:" + timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

某一次的执行结果:

xxxx12...执行完成..task=task-0    耗时:3
xxxx12...执行完成..task=task-3    耗时:2
xxxx14...执行完成..task=task-2    耗时:6
xxxx13...执行完成..task=task-1    耗时:7
xxxx13...执行完成..task=task-6    耗时:0
xxxx12...执行完成..task=task-4    耗时:4
xxxx13...执行完成..task=task-7    耗时:6
xxxx14...执行完成..task=task-5    耗时:7
xxxx12...执行完成..task=task-8    耗时:5
xxxx13...执行完成..task=task-9    耗时:8

版权声明:本文为博主原创文章,未经博主允许不得转载。

[笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池

标签:java   线程池   并发   实战   

原文地址:http://blog.csdn.net/mr_zhuqiang/article/details/47984613

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!