七种线程池
java通过工具类Executors
种各种线程池的工厂方法创建
所有线程池都可使用ExecutorService
接口的引用承接(因为是实现的啊)
(1)CachedThreadPool
Exectors.newCachedThreadPool
- 无长度限制,
- 当新任务加入
CachedThreadPool
时。如果池内其他线程无空闲就产生新的线程执行任务,如果空闲就使用空闲的线程执行任务 - 线程空闲超过一定时间(默认60s,可设置)自动从池中删除
- 可能会造成内存溢出,一般用
FixedThreadPool
代替
(2)FixedThreadPool
Exectors.newFixedThreadPool(线程数量)
- 固定线程数量
- 如果加入任务时线程均不空闲,该任务加入等待队列,当有线程空闲时从等待队列弹出,由刚刚空闲出的线程执行
- 定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
(3)ScheduledThreadPool
Executors.newScheduledThreadPool(线程数)
,返回ScheduledExecutorService
类型- 定长
- 定时及周期性执行任务
- 它会不断重复执行任务,而不是执行了线程数就停
ScheduledThreadPool实例.scheduleAtFixedRate(
() -> {
执行任务
},
执行第一个任务之前等待的时间,
每多少秒启动下一个线程执行此任务,
时间单位
);
(4)SingleThreadExecutor
Executors.newSingleThreadExecutor()
- 容量为
1
,只用一个线程工作 - 多余的任务放入队列
- 任务可以按照指定顺序执行(FIFO,LIFO,优先级)
(5)SingleThreadScheduledExecutor
- 只有一个线程,可以放入多个任务
- 这一个线程通过调度执行这些任务
- 调度类似一个CPU调度多线程执行
- 这也就说明了,当线程中一个任务被阻塞时,整个线程都是被阻塞的
- 示例代码1
public class newSingleThreadScheduledExecutor { private static final ScheduledExecutorService excutor = Executors.newSingleThreadScheduledExecutor(); public static void main(String[] args) { Thread thread1 = new Thread(() -> { long end = new Date().getTime(); System.out.println("time wait:" + (end - start) + ",this is 线程1"); }, "线程1"); Thread thread2 = new Thread(() -> { long end = new Date().getTime(); System.out.println("time wait:" + (end - start) + ",this is 线程2"); }, "线程2"); excutor.scheduleWithFixedDelay(thread1, 0, 1, TimeUnit.SECONDS); excutor.scheduleWithFixedDelay(thread2, 0, 2, TimeUnit.SECONDS); } }
(6)ForkJoinWorkerThread
- 任务盗取:其中的每一个线程维护自己的任务队列,当自己的任务队列中的任务执行完,从其他任务队列拿任务继续执行
- 和普通线程池不同,任务并不是交给线程池中的队列,而是放到线程自己的队列(正如上文
WorkStealingPoll
中所说的那样) - 它采用的是分治法,将大任务分成几个小任务,小任务再划分小任务
- 示例代码2
// 计算1加到999999的总和,每100进行分割,让每一百个数同时相加,返回总和 public class SumTask extends RecursiveTask<Integer> { private Integer start = 0; private Integer end = 0; public SumTask(int start, int end) { this.start = start; this.end = end; } @Override protected Integer compute() { if (end - start < 100) { //小于100时直接返回结果 int sumResult = 0; for (int i = start; i <= end; i++) { sumResult += i; } return sumResult; } else { //大于一百时进行分割 int middle = (end + start) / 2; SumTask leftSum = new SumTask(this.start, middle); SumTask rightSum = new SumTask(middle, this.end); // 拆分任务 leftSum.fork(); rightSum.fork(); // 执行左右任务,并返回结果 return leftSum.join() + rightSum.join(); } } public static void main(String[] args) { SumTask sumTask = new SumTask(1, 999999); sumTask.fork(); // 开始执行 System.out.print("result:" + sumTask.join()); } }
(7)WorkStealingPool
- 任务盗取
- 不是
ThreadPoolExecutor
的扩展,是新的线程池类ForkJoinPool
的扩展 - 虽然父类
ForkJoinWorkerThread
也有任务盗取,但是父类名字上强调分治,WorkStealingPool
从名字上更强调任务盗取,更加专业化 - 适合使用在很费时的操作上