在处理大量任务时,重复利用线程可以提高程序执行效率,因此线程池应运而生。
同时,线程池还可以提供一些额外的功能,例如线程池的大小控制、线程池的任务队列、线程池的拒绝策略等。线程池中通常维护一个线程队列,线程队列中保存着已创建的线程,当有新的任务需要执行时,线程池中的线程就可以从队列中取出一个线程来执行任务,任务执行完毕后线程可以被放回线程队列中,等待下一个任务的到来
在HotSpotVM的线程模型中,Java线程(java.lang.Thread)被一对一映射为本地操作系统线程
Java线程启动时会创建一个本地操作系统线程;当该 Java 线程终止时,这个操作系统线程也会被回收。操作系统会调度所有线程并将它们分配给可用的CPU
Executor框架包含的主要的类与接口如图所示
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
参数介绍:
ThreadPoolExecutor通常使用工厂类Executors来创建,包括3种ThreadPoolExecutor类型:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
由于为LinkedBlockingQueue无界队列(长度Integer.MAX_VALUE),所以会出现如下情景:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
corePool和maximumPoolSize 均被设置成了1,其他影响和运行方式都与FixedThreadPool相同
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), handler);
}
ScheduledThreadPoolExecutor为了实现周期性任务对ThreadPoolExecutor做了如下修改:
ScheduledThreadPoolExecutor通常使用工厂类Executors来创建,2种类型:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
ScheduledThreadPoolExecutor 适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
SingleThreadScheduledExecutor 适用于需要单个后台线程执行周期任务,同时需要保证顺序地执行各个任务的应用场景
Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。当我们把Runnable接口或Callable接口的实现类提交(submit)给 ThreadPoolExecutor或ScheduledThreadPoolExecutor时,ThreadPoolExecutor或ScheduledThreadPoolExecutor会向我们返回一个FutureTask对象
package com.bierce;
import java.util.concurrent.*;
public class TestThreadPoolExecutor {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
//方式一:Runnable方式的分配10个任务提交给线程池
ThreadPoolDemo threadPoolDemo = new ThreadPoolDemo();
for (int i = 0; i <= 10; i++) {
executorService.submit(threadPoolDemo);
}
//方式二:Callable方式的分配10个任务提交给线程池
for (int i = 0; i <= 10; i++) {
Future
package com.bierce;
import java.util.Random;
import java.util.concurrent.*;
public class TestScheduleThreadPool {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
for (int i = 1; i <=5 ; i++) {
//调用schedule方法执行任务
Future random = scheduledExecutorService.schedule(new Callable() {
@Override
public Integer call() throws Exception {
int random = new Random().nextInt(100);
System.out.println(Thread.currentThread().getName() + ":" + random);
return random;
}
},1,TimeUnit.SECONDS); //每隔一秒执行一个任务
System.out.println(random.get());
}
scheduledExecutorService.shutdown(); //关闭线程池
}
}