目录
一.什么是线程池
二.线程池的好处是什么
三.四种基本线程池及其使用
newCachedThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
线程池的四种拒绝策略
选择一:AbortPolicy
选择二:CallerRunsPolicy
选择三:DiscardPolicy
选择四:DiscardOldestPolicy
简单来说,就是在系统的内存里面开辟一个容器用来存放线程
一旦线程结束之后,系统不会立刻回收销毁该线程,而是等他继续在容器里面
如果有其他任务需要调用该线程,就直接从容器里面拿出来
从而不必重新new和销毁线程
降低资源销毁:通过重复利用已经创建的线程,降低线程创建和销毁造成的消耗。
提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
防止服务器过载:形成内存溢出,或者CPU耗尽。.
提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控。
创建一个无最大容量的线程池
如果当前池子里的线程超过正在处理的线程数量,可回收空闲线程,如果池内没有该线程,则向池中放入一个新线程
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class mode9 {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
int j = i;
pool.execute(()->{
System.out.println(Thread.currentThread().getName() + "," + j);
});
}
}
}
创建一个有容量的线程池
可控制线程最大并发数,超出的线程会在队列中等待
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class demo10 {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 3; i++) {
int j = i;
pool.execute(()->{
System.out.println(Thread.currentThread().getName()+j);
});
}
}
}
创建一个有容量,并且能控制运行时间的线程池
public class demo11 {
public static void main(String[] args) {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 5; i++) {
int j = i;
pool.schedule(()->{
System.out.println(Thread.currentThread().getName()+j);
},3,TimeUnit.SECONDS);
}
}
}
采取优先级方式,从始至终都只有一个线程在运行(效率降低,安全性提升)
和第一个newCachedThreadPool基本上没什么区别,就是在他的基础上限定了只能同时运行一个罢了
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class demo12 {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
int j = i;
pool.execute(()->{
System.out.println(Thread.currentThread().getName()+j);
});
}
}
}
1.AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满,默认该方式。
2.CallerRunsPolicy:直接调用execute来执行当前任务。
3.DiscardPolicy:丢弃任务,但是不抛出异常。
4.DiscardOldestPolicy:抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。先从任务队列中弹出最先加入的任务,空出一个位置,然后再次执行execute方法把任务加入队列。
对于上面四种方式我们来举例
假如说,你正在打游戏,这个时候你的老板突然打电话来让你去工作,你就有如下四种选择
哇的一声,哭出来,表示日子过不下去了,打游戏都不让我打了
这个时候,因为你在哭,不仅游戏没有继续打,而且老板让你去工作这件事也没执行
两件事都同时停下了(报错)
直接回怼老板:自己开的公司,就该自己去做事情,别麻烦我
老板听到这句话,只好创建一个属于老板自己的线程,自己去开始工作
(注意,这里老板创建了一个属于自己的进程)
(也就是说发起者创建了一个属于自己的进程来执行,而不要你执行了)
你无视了老板的电话,继续打游戏
这样老板也不知道你什么情况
你任然能继续你手头的工作而且不会报错
你查看了一下时间表
放假是周六和周日
今天是周六
于是你选择抛弃周日
将最后的周日的任务改为执行老板的工作