一、线程池
- 第四种获取线程的方法:线程池,一个ExecutorService,它使用可能的几个线程池之一执行每个提交的任务,通常使用Executors 工厂方法配置。
- 线程池可以解决两个问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个ThreadPoolExecutor还维护着一些基本的统计数据,如完成的任务数。
- 为了便于跨大量上下文使用,此类提供了很多可调整的参数和扩展钩子(hook)。但是强烈建议程序员使用较为方便的Executors工厂方法:
> ExecutorService Executors.newCachedThreadPool()
缓存线程池,线程池的数量不固定,可以根据需求自动更改线程数量
> ExecutorService Executors.newFixedThreadPool(int)
创建固定大小的线程池
> ExecutorService Executors.newSingleThreadExecutor()
单个后台线程
> ScheduledExecutorService newScheduledThreadPool()
创建固定大小的线程池,可以延迟或定时地执行任务
他们均为大多数使用场景预定义了设置。
二、Demo
package com.yuxx.juc;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestThreadPool {
public static void main(String[] args) throws Exception {
//1. 创建线程池
ExecutorService pool = Executors.newFixedThreadPool(5);
ThreadCallablePoolDemo tcpd = new ThreadCallablePoolDemo();
List<Future<Integer>> list = new ArrayList<>();
for(int i = 1;i<=10;i++) {
Future<Integer> future = pool.submit(tcpd);
list.add(future);
}
for(Future<Integer> future:list) {
System.out.println(future.get());
}
pool.shutdown();
}
}
class ThreadCallablePoolDemo implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
System.out.println(Thread.currentThread().getName() + " : i = " + i + ",sum = " + sum);
}
return sum;
}
}
class ThreadPoolDemo implements Runnable{
private int i = 0;
@Override
public void run() {
while(i<=100) {
System.out.println(Thread.currentThread().getName() + " : " + i++);
}
}
}
三、线程池的体系结构
java.util.concurrent.Executor : 负责线程使用和调度的根接口
|-- ExecutorService 子接口 :线程池的主要接口
|-- ThreadPoolExecutor :线程池的实现类
|-- ScheduledExecutorService:子接口,负责线程的调度
|-- ScheduledThreadPoolExecutor:继承ThreadPoolExecutor,实现ScheduledThreadPoolExecutor
四、线程调度
一、ScheduledExecutorService
一个ExecutorService,可以安排在给定的延迟后运行或定期执行的命令。
二、Demo
package com.yuxx.juc;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class TestScheduledThreadPool {
public static void main(String[] args) throws Exception {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
Future<Integer> result = pool.schedule(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int num = new Random().nextInt(100);
System.out.println(Thread.currentThread().getName() + " : " + num);
return num;
}
}, 2, TimeUnit.SECONDS);
System.out.println(result.get());
}
pool.shutdown();
}
}