线程池的7种创建方式
一. 线程的缺点
1:线程的创建需要开辟三个内存资源:本地方法栈,虚拟机栈,程序计数器等线程私有变量的内存,同时销毁的时候需要销毁以上三个区域的内存,频繁的创建和消耗会带来一定的性能开销。
2:在任务量远大于线程可以处理的任务量的时候, 使用线程不能很好的管理任务和友好的拒绝任务。
3:阿里开发手册要求:
[强制]线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。
如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换” 的问题。
二 .线程池
1.定义:使用池化技术来管理和使用线程的技术
2.线程池的优点:
(1)可以避免频繁的创建和消耗线程
(2)可以更好地管理线程的个数和资源的个数
(3)拥有更多功能,比如线程池可以进行定时任务的执行。
(4)线程池可以更友好的拒绝不能处理的任务
3.线程池的创建方式(共7种):
(1)创建固定个数的线程池(任务数趋向无限大,可能会造成OOM,谨慎使用)
public class ThreadPoolDemo1 {
public static void main(String[] args) {
//创建一个固定个数的线程池
ExecutorService service = Executors.newFixedThreadPool(10);//最大为10
for (int i = 0; i < 2; i++) {
//执行任务
service.execute(new Runnable() {
@Override
public void run() {
System.out.println("线程名:" + Thread.currentThread().getName());
}
});
问题:创建了10个线程来执行2个任务,那当前程序创建了几个线程?
答: 创建了2个线程
(2)创建带缓存的线程池(根据任务数量生成对应的线程数)
public class ThreadPoolDemo3 {
public static void main(String[] args) {
//创建带缓存的线程池
ExecutorService service = Executors.newCachedThreadPool();
//执行十个任务
for (int i = 0; i < 10 ; i++) {
service.execute(new Runnable() {
@Override
public void run() {
System.out.println("线程名:"+Thread.currentThread().getName());
}
});
}
}
}
适用场景:有大量短期任务时newCachedThreadPool() 根据当前的任务创建一定数量的线程池
(3)创建可以执行定时任务的线程池
【1】 scheduleWithFixedDelay的使用
public class ThreadPoolDemo4 {
public static void main(String[] args) {
//创建可以执行定时任务的线程池
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
//执行任务
service.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:"+new Date());
}
},1,3, TimeUnit.SECONDS);
}
}
参数1:线程池的任务
参数2:定时任务延迟多长时间开始执行
参数3:定时任务执行频率
参数4:配合参数2和参数3使用的时间单位
【 2】 schedule使用
public class ThreadPoolDemo6 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
System.out.println("执行任务之前:"+new Date());
//执行任务
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:"+new Date());
}
},3, TimeUnit.SECONDS);
}
}
以上两者区别:
(1)schedule没有延迟执行的时间设置
(2)schedule定时任务只能执行一次
【3】scheduleAtFixedRate使用
public class ThreadPoolDemo7 {
public static void main