源码图:
源码:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
代码实现:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();// 缓存线程池,无上限
for (int i = 0; i < 100; i++) {
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
cachedThreadPool.shutdown();// 将线程池关闭 在做项目的时候一般是不会将线程池关闭的
B.newFixedThreadPool创建一个定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待
源码图:
源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
代码实现:
public static void main(String[] args) throws InterruptedException, ExecutionException {
int processors = Runtime.getRuntime().availableProcessors();// 获得计算机有几个内核
// System.out.println("pro : " + processors);
//第一种线程池:固定个数的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(processors * 100);// 固定线程个数的线程池 让一个CPU核绑定100个线程,这种方式经常使用.
// System.out.println(fixedThreadPool);
for (int i = 0; i < 10; i++) {
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());// pool-1-thread-1
}
});
}
fixedThreadPool.shutdown();// 将线程池关闭 在做项目的时候一般是不会将线程池关闭的.
C.newSingleThreadExecutor创建一个单线程化的线程池,只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序进行
源码图:
源码:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
代码实现:
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();// 单一线程池,永远会维护存在一条线程
for (int i = 0; i < 10; i++) {
final int j = i;
singleThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":"
+ j);
}
});
}
singleThreadPool.shutdown();
D.newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行
源码图如下,这个比较特殊,但内部还是使用的ThreadPoolExecutor/第四种线程池:固定个数的线程池,相比于第二个固定个数的线程池 强大在 ①可以执行延时任务,②也可以执行带有返回值的任务。scheduledThreadPool.submit(); 执行带有返回值的任务scheduledThreadPool.schedule() 用来执行延时任务.
第一步:ScheduledThreadPoolExecutor点进去
第二步:super点进去
第三步:可以发现还是使用的ThreadPoolExecutor
源码:
第一步源码:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
第二步源码:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
第三步源码:也就是ThreadPoolExecutor源码的一部分,下面会细说。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
代码实现:
FutureTaskft = new FutureTask (new Callable () { @Override public String call() throws Exception { System.out.println("hello"); return Thread.currentThread().getName(); } }); scheduledThreadPool.submit(ft); String result = ft.get();//通过FutureTask对象获得返回值. System.out.println("result : "+result); scheduledThreadPool.schedule(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+" : bobm!"); } }, 3, TimeUnit.SECONDS); }
注意:阿里巴巴java开发手册中提到,不使用默认线程池,并说明了原因。
ThreadPoolExecutor 源码:
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;
}
参数分析
A.corePoolSize:核心线程数,初始创建的线程都是核心线程数,线程池中正常情况下始终保留该大小的线程实例存活 B.maximumPoolSize:最大线程数,当核心线程都在执行任务,任务队列满的情况下会创建非核心线程来执行任务,当非核心线程处于空闲时间,且超过keepAliveTime时,会销毁非核心线程 C.keepAliveTime:存活时间,用于控制非核心线程的空闲时存活时间 D.unit:存活时间的单位。具体是TimeUnit枚举,有毫秒、秒、分钟、小时等等 E.workQueue:线程池的任务队列,当线程池的核心线程都处于繁忙状态,且有新任务到来,则会进入任务队列,当任务队列满了,则会创建非核心线程执行新任务 threadFactory:线程池创建线程实例的线程工厂,一般默认为Executors.defaultThreadFactory F.handler:线程池拒绝策略,当核心线程全部繁忙,任务队列已满,非核心线程全部繁忙,会触发线程池拒绝策略。有四种策略: AbortPolicy(默认),直接抛出异常并且拒绝。源码图:
源码:
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
CallerRunsPolicy:该策略既不会抛弃任务,也不会抛出异常,而是将任务回推到调用者。"顾名思义,在饱和的情况下,调用者会执行该任务。
源码图:
源码:
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
DiscardOldestPolicy:丢弃线程队列的旧的任务,将新的任务添加
源码图:
源码:
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
DiscardPolicy:由调用线程处理该任务 【谁调用,谁处理】
源码图:
源码:
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 发现这里面什么都没做
}
}
自定义线程池(多线程并发编程使用execute和submit执行)
代码示例:
public class TestThreadPoolExecutors {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 使用ThreadPoolExecutor创建线程池
ExecutorService executor = new ThreadPoolExecutor(10, 20, 30, TimeUnit.SECONDS, new LinkedBlockingQueue());
// 用execute执行,没有返回值结果
executor.execute(() -> {
for (int i = 0; i < 10; i++) {
try {
// 每次执行前睡眠1秒钟(方便我们区别)
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "-" + "用execute执行的test线程池" + "-" + i);
} catch (Exception ex) {
System.out.println("异常处理");
}
}
});
//用submit执行,有返回值结果
Future> result = executor.submit(() -> {
for (int i = 101; i < 106; i++) {
System.out.println(Thread.currentThread().getName() + "-" + "用submit执行的test线程池" + "-" + i);
}
});
// 打印返回值
System.out.println(result);
// 执行完成记得关闭,不然程序一直在进行
executor.shutdown();
}
}
运行结果:
以上就是jdk自带线程池ThreadPoolExecutor的理解



