简述多线程
1 线程池
1.1 什么是线程池
线程池是一种多线程处理形式,处理过程中将任务添加到队列中,随着创建线程而开始自动执行任务。
注意点
1 任务一般是实现Runable接口的实例
2 与Thread创建线程不同,当我们用实现Runable接口的实例的任务时,我们需要将任务的对象添加到Thread中去。
3 线程池则不需要将任务添加到Thread中在thread.start()执行,用线程池创建的线程随着创建线程而自动执行任务。
下面截取部分代码说明Thread执行线程与线程池执行线程的区别:
1 Thread执行线程
2 线程池执行线程
1.2 为什么要使用线程池
线程池可以根据系统需求和硬件环境来灵活的控制线程的数量,且用线程池创建的线程方便管理和控制,提高系统运行效率,减轻系统的运行压力。
1.3 线程池运用场景
1 商品秒杀项目
2 12306抢票
3 网盘下载
4 …
2 线程池工作原理
2.1 线程池的组成
线程池由以下几部分组成
1 核心线程数(corePoolSize)(必需):默认状态下,会一直存活,但是当将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
2 最大线程数(maximumPoolSize)(必需0):线程池能容纳的最大活跃线程数,当活跃线程数达到该数值后,后续的新任务将会阻塞。
3 任务队列(workQueue)(必需):能容纳的最多阻塞线程数
4 设置闲时时长(keepAliveTime)(必需):线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
5 参数时间单位(unit)(必需):指定 keepAliveTime 参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。
6 拒绝策略(handler)(不必需):当线程池中的线程已达到最大线程池容量时,外面的线程想要在进入线程池,线程池需要采取的方式
7 线程工厂(threadFactory)(可选):线程工厂。用于指定为线程池创建新线程的方式。
线程池结构如下
2.2 线程池工作原理
3 线程池使用
3.1 构造方法
public ThreadPoolExecutor(int corePoolSize, //核心线程数量
int maximumPoolSize,// 最大线程数
long keepAliveTime, // 最大空闲时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 饱和处理机制
)
3.2创建线程池
public class ThreadPoolDemo {
CountDownLatch countDownLatch = new CountDownLatch(MAX_TURN);
public static final int SLEEP_GAP = 500;
public static final int MAX_TURN = 5;
//异步的执行目标类
public static class TargetTask implements Runnable {
CountDownLatch countDownLatch;
static AtomicInteger taskNo = new AtomicInteger(1);
protected String taskName;
public TargetTask() {
taskName = "task-" + taskNo.get();
taskNo.incrementAndGet();
}
public TargetTask(CountDownLatch countDownLatch) {
this();
this.countDownLatch = countDownLatch;
}
public void run() {
System.out.println("任务:" + taskName + " doing");
try {
Thread.sleep(SLEEP_GAP);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(taskName + " 运行结束.");
countDownLatch.countDown();
}
@Override
public String toString() {
return "TargetTask{" + taskName + '}';
}
}
//测试用例:只有一条线程的线程池
@Test
public void testSingleThreadExecutor() {
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < MAX_TURN; i++) {
pool.execute(new TargetTask(countDownLatch));
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// //关闭线程池
pool.shutdown();
}
//测试用例:只有3条线程固定大小的线程池
@Test
public void testNewFixedThreadPool() throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < MAX_TURN; i++) {
pool.execute(new TargetTask(countDownLatch));
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//关闭线程池
pool.shutdown();
}
/**
* CachedThredPool:线程数没有限制
* @throws InterruptedException
*/
@Test
public void testNewCachedThreadPool() throws InterruptedException {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < MAX_TURN; i++) {
pool.execute(new TargetTask(countDownLatch));
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//关闭线程池
pool.shutdown();
}
//测试用例:“可调度线程池”
@Test
public void testNewScheduledThreadPool() {
ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(2);
for (int i = 0; i < 2; i++) {
scheduled.scheduleAtFixedRate(new TargetTask(countDownLatch),
0, 5000, TimeUnit.MILLISECONDS);
}
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//关闭线程池
scheduled.shutdown();
}
@Test
public void testThreadPoolExecutor() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, //corePoolSize
4, //maximumPoolSize
100, //keepAliveTime
TimeUnit.SECONDS, //unit
new LinkedBlockingDeque<>(2), new ThreadPoolExecutor.CallerRunsPolicy());//workQueue
for (int i = 0; i < 7; i++) {
final int taskIndex = i;
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " taskIndex = " + taskIndex );
try {
Thread.sleep(10000);
// Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
executor.execute(task);
}
while (true) {
//每隔 1 秒,输出线程池的工作任务数量、总计的任务数量
System.out.printf("- activeCount: %d - taskCount: %d\r\n", executor.getActiveCount(), executor.getTaskCount());
ThreadUtil.sleepSeconds(1);
}
}
}