Executors

1.概述

初学Java多线程,常使用ThreadRunnable创建、启动线程。如下例:

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
});
t1.start();

我们需要自己创建、启动Thread对象。

2. 使用Executors执行线程

一些已有的执行器可以帮我们管理Thread对象。你无需自己创建与控制Thread对象。

比如,你不用在代码中编写new Thread或者thread1.start()也一样可以使用多线程。如下例:

ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {//5个任务
    exec.submit(new Runnable() {
        @Override
        public void run() {            
            System.out.println(Thread.currentThread().getName()+" doing task");
         }
     });
}
exec.shutdown();  //关闭线程池

输出如下:

pool-1-thread-2 doing task
pool-1-thread-1 doing task
pool-1-thread-3 doing task
pool-1-thread-4 doing task
pool-1-thread-5 doing task

从输出我们可以看到,exec使用了线程池1中的5个线程做了这几个任务。

这个例子中exec这个Executor负责管理任务,所谓的任务在这里就是实现了Runnable接口的匿名内部类。

至于要使用几个线程,什么时候启动这些线程,是用线程池还是用单个线程来完成这些任务,我们无需操心。完全由exec这个执行器来负责。

在这里exec(newCachedThreadPool)指向是一个可以根据需求创建新线程的线程池。

2.1 Executors工具类

Executors相当于执行器的工厂类,包含各种常用执行器的工厂方法,可以直接创建常用的执行器。几种常用的执行器(静态方法)如下:

Executors.newCachedThreadPool();        //创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE

Executors.newFixedThreadPool(int);    //创建固定容量大小的缓冲池

Executors.newSingleThreadExecutor();   //创建容量为1的缓冲池

Executors.newScheduledThreadPool(corePoolSize);       // 创建一个定长线程池,支持定时及周期性任务执行。

在java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是经常使用Executors类中提供的几个静态方法来创建线程池。

从下面它们的具体实现来看,它们实际上也是调用了ThreadPoolExecutor,只不过参数都已配置好了。

2.1.1 newCachedThreadPool()

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程线程池中曾经创建的线程,在完成某个任务后也许会被用来完成另外一项任务,若无可回收,则新建线程。

实现原理:将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,

使用的是没有容量的SynchronousQueue(无界),但其maximumPoolSize是无界的,也就是说来了任务就创建线程运行,并且当主线程提交任务的速度高于maximumPoolSize中线程处理任务的速度时CachedThreadPool将会不断的创建新的线程。

适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器。在极端情况下,CachedThreadPool会因为创建过多线程而耗尽CPU和内存资源。

60L:当线程空闲超过60秒,就销毁线程。

2.1.2 newFixedThreadPool(int nThreads)

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

这个创建的线程池corePoolSize和maximum PoolSize值是相等的,都为nThreads。

keepAliveTime=0L:线程一空闲,就立即销毁。

它使用的LinkedBlockingQueue(无界队列)。使用该队列作为工作队列会对线程池产生如下影响:

(1)当前线程池中的线程数量达到corePoolSize后,新的任务将在无界队列中等待;

(2)由于我们使用的是无界队列,所以参数maximumPoolSize和keepAliveTime无效;

(3)由于使用无界队列,运行中的FixedThreadPool不会拒绝任务(当然此时是未执行shutdown和shutdownNow方法)。

所以不会去调用RejectExecutionHandler的rejectExecution方法抛出异常。

创建一个定长线程池(最大线程数是nThreads),可控制线程最大并发数,超出的线程会在队列LinkedBlockingQueue中等待。适用于为了满足资源管理要求,而需要限制当前线程数量的应用场景。

线程在执行完自己当前任务后,会在循环中反复从LinkedBlockingQueue获取任务来执行。

2.1.3 newSingleThreadExecutor()

public static ExecutorService newSingleThreadPool() {
    return new FinalizableDelegatedExecutorService 
                (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
}

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。这种特点可以被用来处理共享资源的问题而不需要考虑同步的问题。

适用于需要保证顺序地执行各个任务,并且在任意时间点,不会有多个线程是活动的应用场景。

它使用的LinkedBlockingQueue(无界队列)。

2.1.4 newSingleThreadScheduledExector() 

只包含一个线程的定时及周期线程池。即使任务再多,也只用1个线程完成任务。

2.1.5 newScheduledThreadPool ()

创建一个定长线程池,支持定时及周期性任务执行。

适用于多个后台线程执行周期任务,同时为了满足资源管理的需求而限制后台线程的数量的应用场景。

2.1.6 表格对比

 使用的阻塞队列corePoolSizemaximumPoolSize适用场景
newCachedThreadPool()

SynchronousQueue

无界

0Integer.MAX_VALUE很多的短期异步任务的小程序,或者是负载较轻的服务器。
newFixedThreadPool()

LinkedBlockingQueue

无界

=nThreads=nThreads为了满足资源管理要求,而需要限制当前线程数量
newSingleThreadExecutor()

LinkedBlockingQueue

无界

11需要保证顺序地执行各个任务,并且在任意时间点,不会有多个线程是活动
newSingleThreadScheduledExector() 一个线程 定时及周期线程池
newScheduledThreadPool () 定长线程池 多个后台线程执行周期任务,限制后台线程的数量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值