每次 new Thread 新建对象,性能差。
线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或 OOM。
缺少更多功能,如更多执行、定期执行、线程中断。
重用存在的线程,减少对象创建、消亡的开销,性能佳。
可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。
提供定时执行、定期执行、单线程、并发数控制等功能。
corePoolSize :核心线程数量。
maximumPoolSize :线程最大线程数。
workQueue :阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响。
keepAliveTime :线程没有任务执行时最多保持多久时间终止 unit : keepAliveTime 的时间单位。
threadFactory :线程工厂,用来创建线程。
rejectHandler :当拒绝处理任务时的策略。
线程池作用就是限制系统中执行线程的数量。
根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。
用线程池控制线程数量,其他线程排 队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池 中有等待的工作线程,就可以开始运行了,否则进入等待队列。
1: 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2: 可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
拓展: Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。
execute ():提交任务,交给线程池执行
submit ():提交任务,能够返回执行结果 execute + Future
shutdown ():关闭线程池,等待任务都执行完
shutdownNow ():关闭线程池,不等待任务执行完
getTaskCount ():线程池已执行和未执行的任务总数
getCompletedTaskCount ():已完成的任务数量
getPoolSize ():线程池当前的线程数量
getActiveCount ():当前线程池中正在执行任务的线程数量
Executors.newCachedThreadPool
package com.mmall.concurrency.example.threadPool;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
* 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
*/
@Slf4j
public class newCachedThreadPoolExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
//写法一,直接内部
// executorService.execute(new Runnable() {
// @Override
// public void run() {
// log.info("task:{}", index);
// }
// });
//写法二 ,
executorService.execute(()->{
outIndex(index);
});
}
//用完记得关闭
executorService.shutdown();
}
public static void outIndex(int index){
log.info("task:{}", index);
}
}
Executors.newFixedThreadPool
package com.mmall.concurrency.example.threadPool;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
* 因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
*定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。
*/
@Slf4j
public class newFixedThreadPoolExample {
public static void main(String[] args) throws Exception{
ExecutorService executorService= Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index=i;
executorService.execute(()->{
outIndex(index);
});
}
}
public static void outIndex(int index) {
log.info("task:{}", index);
try {
Thread.sleep(2000);
} catch (Exception e) {
log.error("error:{}",e);
}
}
/**
因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
16:28:32.281 [pool-1-thread-1] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:0
16:28:32.281 [pool-1-thread-2] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:1
16:28:32.281 [pool-1-thread-3] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:2
16:28:34.290 [pool-1-thread-3] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:4
16:28:34.290 [pool-1-thread-2] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:5
16:28:34.290 [pool-1-thread-1] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:3
16:28:36.292 [pool-1-thread-3] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:6
16:28:36.292 [pool-1-thread-2] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:7
16:28:36.292 [pool-1-thread-1] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:8
16:28:38.294 [pool-1-thread-3] INFO com.mmall.concurrency.example.threadPool.newFixedThreadPoolExample - task:9
**/
}
Executors.newScheduledThreadPool
package com.mmall.concurrency.example.threadPool;
/**
* 创建一个定长线程池,支持定时及周期性任务执行。
* ScheduledExecutorService比Timer更安全,功能更强大
*/
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 创建一个定长线程池,支持定时及周期性任务执行。
* ScheduledExecutorService比Timer更安全,功能更强大
*/
@Slf4j
public class newScheduledThreadPoolExample {
public static void main(String[] args) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
//表示延迟3秒执行
executorService.schedule(()-> {
outIndex(1);
}, 3, TimeUnit.SECONDS);
//表示延迟1秒后每3秒执行一次。
executorService.scheduleAtFixedRate(()-> {
outIndex(2);
}, 1, 3, TimeUnit.SECONDS);
// executorService.shutdown();
// Timer timerx = new Timer();
// timerx.schedule(new TimerTask() {
// @Override
// public void run() {
// log.warn("timerx run");
// }
// }, new Date(), 5 * 1000);
}
public static void outIndex(int index) {
log.info("task:{}", index);
try {
Thread.sleep(2000);
} catch (Exception e) {
log.error("error:{}", e);
}
}
}
Executors.newSingleThreadExecutor
package com.mmall.concurrency.example.threadPool;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
*/
@Slf4j
public class newSingleThreadExecutorExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
executorService.execute(()->{
outIndex(index);
});
}
executorService.shutdown();
}
public static void outIndex(int index) {
log.info("task:{}", index);
try {
Thread.sleep(2000);
} catch (Exception e) {
log.error("error:{}", e);
}
}
}