文章大致介绍线程池的用途,以及代码的基本实现
在使用多线程技术时,难免会出现创建了多个线程,线程执行任务时间较短,大部分时间都用在创建和销毁线程中,大大降低了系统的效率。
线程池技术 ,可以想象把所有使用的线程都放到一个容器中,池中的的线程可以重复利用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。
线程池的好处:
- 降低资源消耗
- 提高响应速度
- 提高线程的可管理性
线程池主要有以下几种分类:
缓存线程池、定长线程池、单线程线程池、周期性任务定长线程池
一、缓存线程池
长度无限制
执行流程:
- 判断线程池是否存在空闲线程
- 存在则使用
- 不存在则创建线程,并放入线程池,然后使用
ExecutorService service = Executors.newCachedThreadPool();
//指挥线程池执行新的任务
service.execute(new Runnable() {
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + "锄禾日当午")
}
});
service.execute(new Runnable() {
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + "锄禾日当午")
}
});
service.execute(new Runnable() {
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + "锄禾日当午")
}
});
// 上面所有线程任务都执行完毕之后,使主线程休眠,发现使用的还是之前创建的线程,并没有重新创建
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
}
});
二、定长线程池
长度是指定的值
执行流程:
- 判断线程池是否存在空闲线程
- 存在则使用
- 不存在空闲线程,且线程池未满的情况下,则创建线程,并放入线程池,然后使用
- 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
ExecutorService service = Executors.newFixedThreadPool(2);//构造方法传入固定长度
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
try{
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
try{
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
});
//当两个线程都处于休眠状态时,线程池中没有可用的线程,不会创建新的线程,等有空闲线程时再执行
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
}
});
三、单线程线程池
执行流程:
- 判断线程池的那个线程是否空闲
- 空闲则使用
- 不空闲,则等待池中的单个线程空闲后使用
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "锄禾日当午");
}
});
// 均为同一个线程执行
四、周期性任务定长线程池
定长线程池
执行流程:
- 判断线程池是否存在空闲线程
- 存在则使用
- 不存在空闲线程,且线程池未满的情况下,则创建线程并放入线程池,然后使用
- 不存在空闲线程,且线程池已满的情况下,则等待线程池存在空闲线程
周期性任务执行:
定时执行,当某个时机触发时,自动执行某任务(多少秒之后或每隔多少秒执行)
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
/**
* 1. 定时执行一次
* 参数1 定时执行的任务
* 参数2 时长数值
* 参数3 时间单位,为TimeUnit 的常量参数
* */
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("锄禾日当午");
}
},5, TimeUnit.SECONDS);
/**
* 周期性执行任务
* 参数1 任务
* 参数2 延迟时长数值(第一次执行多少时间以后)
* 参数3 周期时长数值(往后每隔多久执行)
* 参数4 时长数字的单位
* */
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("汗滴禾下土");
}
},5,1,TimeUnit.SECONDS);