线上代码
package com.gome.home.match.finance.util;
import java.util.concurrent.*;
public class MyTest {
public static void main(String[] args) {
Executor();
}
private static void Executor(){
//创建线程四种方式:
//1.可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
//2.定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
//3.可定时线程池,支持定时及周期性任务执行。
//4.单例线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
//可缓存、定时、定长、单例
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
System.out.println("开始执行:cachedThreadPool=======");
runExecutor(cachedThreadPool);
//可定长线程,核心线程5个,最多创建5个线程 (只会创建5个线程,其他线程共享这5个线程)
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
System.out.println("开始执行:fixedThreadPool=======");
runExecutor(fixedThreadPool);
//单例线程 =>核心线程数1 最大线程数1
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
System.out.println("开始执行:singleThreadExecutor=======");
runExecutor(singleThreadExecutor);
//可定时线程 =>核心线程数3 (延迟三秒执行)
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
System.out.println("开始执行:scheduledThreadPool=======");
runExecutorS(scheduledThreadPool);
// 1、corePoolSize:核心线程数
// * 核心线程会一直存活,及时没有任务需要执行
// * 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理
// * 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭
//
// 2、queueCapacity:任务队列容量(阻塞队列)
// * 当核心线程数达到最大时,新任务会放在队列中排队等待执行
//
// 3、maxPoolSize:最大线程数
// * 当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务
// * 当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常
//
// 4、 keepAliveTime:线程空闲时间
// * 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
// * 如果allowCoreThreadTimeout=true,则会直到线程数量=0
//
// 5、allowCoreThreadTimeout:允许核心线程超时
// 6、rejectedExecutionHandler:任务拒绝处理器
// * 两种情况会拒绝处理任务:
// - 当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务
// - 当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务
// * 线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常
// * ThreadPoolExecutor类有几个内部实现类来处理这类情况:
// - AbortPolicy 丢弃任务,抛运行时异常
// - CallerRunsPolicy 执行任务
// - DiscardPolicy 忽视,什么都不会发生
// - DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务
// * 实现RejectedExecutionHandler接口,可自定义处理器
}
private static void runExecutor(ExecutorService executorService ){
for (int i = 0; i < 10; i++) {
final int i1 = i;
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+",i:"+i1);
});
}
}
//可定时线程 =>核心线程数3 (延迟三秒执行)
private static void runExecutorS(ScheduledExecutorService executorService ){
for (int i = 0; i < 10; i++) {
final int i1 = i;
executorService.schedule(()->{
System.out.println(Thread.currentThread().getName()+",i:"+i1);
System.out.println("耗时:"+ (System.currentTimeMillis() - 1)/1000 +"秒" );
},3,TimeUnit.SECONDS);
}
}
private static void testCLD(){
ConcurrentLinkedDeque<Object> objects = new ConcurrentLinkedDeque<>();
objects.offer("java001");
objects.offer("java002");
System.out.println("度列总数:"+objects.size());
System.out.println("获取队列但不删除:"+objects.peek());
System.out.println("获取队列但不删除,队列总数:"+objects.size());
System.out.println("获取队列并删除:"+objects.poll());
System.out.println("非阻塞队列为空返回Null:"+objects.poll());
System.out.println("非阻塞队列为空返回Null:"+objects.poll());
System.out.println("非阻塞队列为空返回Null:"+objects.poll());
System.out.println("获取队列但不删除,队列总数:"+objects.size());
}
//阻塞式队列
public static void test2() {
long startTime=System.currentTimeMillis();
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
try {
arrayBlockingQueue.offer("A001",3, TimeUnit.SECONDS);
arrayBlockingQueue.offer("A002",3, TimeUnit.SECONDS);
//阻塞式队列超出总数等待(等待时间=设置超时时间)
arrayBlockingQueue.offer("A003",3, TimeUnit.SECONDS);
arrayBlockingQueue.offer("A004",1, TimeUnit.SECONDS);
arrayBlockingQueue.offer("A005",1, TimeUnit.SECONDS);
System.out.println("队列总数:"+arrayBlockingQueue.size());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
//阻塞式队列,如果为空也会等待。
System.out.println(arrayBlockingQueue.poll(1, TimeUnit.SECONDS));
System.out.println("队列剩余总数:"+arrayBlockingQueue.size());
System.out.println("耗时:"+ (System.currentTimeMillis() - startTime)/1000 +"秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
方法 testCLD为阻塞队列
方法 test2 为非阻塞队列
方法 Executor 中可逐个放开注释进行测试,观察运行情况
各种种类的线程池,最终调用的都是 ThreadPoolExecutor构造
可自行百度ThreadPoolExecutor参数都代表什么意思