目录
为什么要用线程池
线程池的好处
Java中的四种线程池
1.缓存线程池
2.定长线程池
3.单线程池
4. 周期性任务定长线程池
为什么要用线程池
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程 就会大大降低 系统的效率,因为频繁创建线程和销毁线程需要时间. 线程池就是一个容纳多个线程的容 器,池中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。
线程池的好处
- 降低资源消耗。
- 提高响应速度。
- 提高线程的可管理性。
Java中的四种线程池
1.缓存线程池
缓存线程池:长度无限制
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在,则创建线程 并放入线程池, 然后使用
package huabcun;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo_2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//创建一个线程池
ExecutorService s = Executors.newCachedThreadPool();
//向线程池中加入新的任务1
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿");
}
});
//向线程池中加入新的任务2
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿好饿");
}
});
//向线程池中加入新的任务3
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿好饿好饿");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//向线程池中加入新的任务4
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"真的好饿好饿好饿");
}
});
}
}
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程 就会大大降低 系统的效率,因为频繁创建线程和销毁线程需要时间. 线程池就是一个容纳多个线程的容 器,池中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。
- 降低资源消耗。
- 提高响应速度。
- 提高线程的可管理性。
Java中的四种线程池
1.缓存线程池
缓存线程池:长度无限制
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在,则创建线程 并放入线程池, 然后使用
package huabcun;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo_2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//创建一个线程池
ExecutorService s = Executors.newCachedThreadPool();
//向线程池中加入新的任务1
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿");
}
});
//向线程池中加入新的任务2
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿好饿");
}
});
//向线程池中加入新的任务3
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿好饿好饿");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//向线程池中加入新的任务4
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"真的好饿好饿好饿");
}
});
}
}
缓存线程池:长度无限制
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在,则创建线程 并放入线程池, 然后使用
package huabcun;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo_2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//创建一个线程池
ExecutorService s = Executors.newCachedThreadPool();
//向线程池中加入新的任务1
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿");
}
});
//向线程池中加入新的任务2
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿好饿");
}
});
//向线程池中加入新的任务3
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"好饿好饿好饿");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//向线程池中加入新的任务4
s.execute(new Runnable(){
public void run() {
System.out.println(Thread.currentThread().getName()+"真的好饿好饿好饿");
}
});
}
}
结果:发现4个任务三个都是使用的线程2,说明线程池为无限大,当执行第二个任务时第一个任务已经还未完成,执行第三个和第四个,第二个任务已经完成,会复用执行第二个任务的线程,而不用每次新建线程。
2.定长线程池
定长线程池:长度是指定的数值。
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
package dingchang;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo_1 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//创建线程池长度为2
ExecutorService s = Executors.newFixedThreadPool(2);
//线程池任务1,延迟时间可不加为了看起来好理解才加
s.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"想吃虾片");
}
});
//线程池任务2
s.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"想吃呀土豆");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
//线程池任务3
s.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"想吃小蛋糕");
}
});
//线程池任务4
s.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"想吃锅巴");
}
});
//线程池任务5
s.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"想吃小面包");
}
});
}
}
定长线程池:长度是指定的数值。
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
结果:共有五个任务,但线程池规定只能创建两个长度的线程,所以线程1和线程2那个线程先空闲,那个线程给排队的任务3、4、5使用。
3.单线程池
效果与定长线程池效果一致, 创建时传入数值1即可
执行流程: 1. 判断线程池 的那个线程 是否空闲
2. 空闲则使用
4. 不空闲,则等待 池中的单个线程空闲后 使用
package dan;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo_4 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//创建线程池,长度为1
ExecutorService s = Executors.newSingleThreadExecutor(1);
//创建任务1
s.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"线程");
}
});
//创建任务2
s.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"线程2");
}
});
}
}
效果与定长线程池效果一致, 创建时传入数值1即可
执行流程: 1. 判断线程池 的那个线程 是否空闲
2. 空闲则使用
4. 不空闲,则等待 池中的单个线程空闲后 使用
结果:线程池规定只可以创建一个线程,所以两个任务都用线程1
4. 周期性任务定长线程池
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
周期性任务执行时: 定时执行, 当某个时机触发时, 自动执行某任务 .
两个方法实现周期:方法一:schedule:定时执行一次任务
方法二:scheduleAtFixedRate:周期性执行任务
具体使用方法放代码
package zhouqi;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Demo_3 {
public static void main(String[] args) {
ScheduledExecutorService s =Executors.newScheduledThreadPool(2);//创建两个长度的线程池
//方法一:schedule:定时执行一次任务
// 参数一:定时执行的任务
// 参数二:时长数字
// 参数三:时长数字的时长单位TimeUnit的常量指定
s.schedule(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"线程");
}
},3,TimeUnit.SECONDS);
// 方法二:scheduleAtFixedRate:周期性执行任务
// 参数一:任务
// 参数二:延迟时长数字(第一次执行在什么时间以后)
// 参数三:周期时长数字(每隔多久执行一次)
// 参数四:时长数字的单位
s.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"线程2");
}
},5,1,TimeUnit.SECONDS);
}
}
执行流程: 1. 判断线程池是否存在空闲线程
2. 存在则使用
3. 不存在空闲线程,且线程池未满的情况下,则创建线程 并放入线程池, 然后使用
4. 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
周期性任务执行时: 定时执行, 当某个时机触发时, 自动执行某任务 .
两个方法实现周期:方法一:schedule:定时执行一次任务
方法二:scheduleAtFixedRate:周期性执行任务
具体使用方法放代码
结果:3s线程出现,然后线程2一秒出现一次。



