线程池
概念:
当对程序有请求时,程序创建线程去处理该请求,若每有一个请求就创建一个线程去处理,处理完毕后又销毁,那么请求不断时,创建、销毁就会不断重复,这对资源是一种浪费,时间上也会有浪费。线程池技术,就是先创建一个“池”,里面已经创建好合适量的线程,当有任务请求时,重复利用已有线程,减少了不断创建销毁这个过程的开销,同时,因为线程处于已经创建的转态,当有任务来时,可以直接开始执行请求,节省了线程创建时消耗时间(虽然时间好像很少,但是量变引起质变),使应用程序响应更快。
- 一个简单的线程池该有的东西
- 线程池管理器
- 创建、销毁并管理线程池,将工作线程放入线程池中
- 工作线程
- 一个可以循环执行任务的线程,没有任务时就是处于等待状态
- 任务队列
- 将没有处理的任务放在任务队列中
- 任务接口
- 每个任务必须实现的接口,主要用来规定任务的入口、任务完成后的收尾工作、任务的执行状态等等,工作线程通过该接口调度任务的执行
- 线程池管理器
举个例子–简单的线程池应用
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class ExecutorServiceTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
testFixPool();
testSchPool();
testSchePool();
}
//第一个方法
private static void testFixPool() throws InterruptedException, ExecutionException {
//newFixedThreadPool()---创建一个线程池,重用固定数量的线程,从共享无界队列中运行,使用提供的ThreadFactory在需要时创建新线程。
//这里的newFixedThreadPool()中的x是表示一个值,创建x个线程,请自己根据自己需要写入参数
ExecutorService service = Executors.newFixedThreadPool(x);
for (int i = 0; i < 5; i++) {
Future<?> future = service.submit(() -> {
String name = Thread.currentThread().getName();
System.out.println(name + "正在执行任务...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("得到结果:" + future.get());
}
service.shutdown();
}
//第二个方法
private static void testSchPool() throws InterruptedException, ExecutionException {
//newScheduledThreadPool()---创建一个线程池,可以调度命令在给定的延迟之后运行,或定期执行。
//这里的newScheduledThreadPool()中的x是表示一个值,创建x个线程,请自己根据自己需要写入参数
ExecutorService service = Executors.newScheduledThreadPool(x);
for (int i = 0; i < 7; i++) {
Future<?> future = service.submit(() -> {
String name = Thread.currentThread().getName();
System.out.println(name + "正在执行任务...");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("得到结果:" + future.get());
}
service.shutdown();
}
//第三个方法
private static void testSchePool() throws InterruptedException, ExecutionException {
ExecutorService service = Executors.newScheduledThreadPool(2);
Set<Callable<Integer>> tasks = new HashSet<>();
tasks.add(()->{
String name = Thread.currentThread().getName();
for (int i = 0; i < 3; i++) {
System.out.println(name+"搬的"+(i+1)+"块转...");
TimeUnit.SECONDS.sleep(1);
}
return 1;
});
tasks.add(()->{
String name = Thread.currentThread().getName();
for (int i = 0; i < 3; i++) {
System.out.println(name+"吃的第"+(i+1)+"块西瓜...");
TimeUnit.SECONDS.sleep(1);
}
return 2;
});
tasks.add(()->{
String name = Thread.currentThread().getName();
for (int i = 0; i < 3; i++) {
System.out.println(name+"打的第"+(i+1)+"万行代码...");
TimeUnit.SECONDS.sleep(1);
}
return 3;
});
List<Future<Integer>> result = service.invokeAll(tasks);
for (Future<Integer> future : result) {
System.out.println("线程任务执行结果:"+future.get());
}
service.shutdown();
}
}
-
第一个方法执行
-
创建2个线程运行结果:
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null -
创建5个线程运行结果:
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-3正在执行任务…
得到结果:null
pool-1-thread-4正在执行任务…
得到结果:null
pool-1-thread-5正在执行任务…
得到结果:null -
创建6个线程运行结果:
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-3正在执行任务…
得到结果:null
pool-1-thread-4正在执行任务…
得到结果:null
pool-1-thread-5正在执行任务…
得到结果:null
-
-
第二个方法执行
-
创建3个线程运行结果:
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-3正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null -
创建建7个线程运行结果:
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-3正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-4正在执行任务…
得到结果:null -
创建9个线程运行结果:
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-1正在执行任务…
得到结果:null
pool-1-thread-3正在执行任务…
得到结果:null
pool-1-thread-2正在执行任务…
得到结果:null
pool-1-thread-4正在执行任务…
得到结果:null
-
-
第三个方法执行
- 创建2个线程运行结果:
pool-1-thread-1打的第1万行代码…
pool-1-thread-2吃的第1块西瓜…
pool-1-thread-1打的第2万行代码…
pool-1-thread-2吃的第2块西瓜…
pool-1-thread-1打的第3万行代码…
pool-1-thread-2吃的第3块西瓜…
pool-1-thread-1搬的1块转…
pool-1-thread-1搬的2块转…
pool-1-thread-1搬的3块转…
线程任务执行结果:3
线程任务执行结果:2
线程任务执行结果:1 - 创建3个线程运行结果:
pool-1-thread-2打的第1万行代码…
pool-1-thread-1吃的第1块西瓜…
pool-1-thread-3搬的1块转…
pool-1-thread-2打的第2万行代码…
pool-1-thread-1吃的第2块西瓜…
pool-1-thread-3搬的2块转…
pool-1-thread-1吃的第3块西瓜…
pool-1-thread-2打的第3万行代码…
pool-1-thread-3搬的3块转…
线程任务执行结果:3
线程任务执行结果:2
线程任务执行结果:1 - 创建5个运行结果:
pool-1-thread-1打的第2万行代码…
pool-1-thread-3吃的第2块西瓜…
pool-1-thread-2搬的2块转…
pool-1-thread-1打的第3万行代码…
pool-1-thread-3吃的第3块西瓜…
pool-1-thread-2搬的3块转…
线程任务执行结果:3
线程任务执行结果:2
线程任务执行结果:1
- 创建2个线程运行结果:
Executors中不同的方法创建的线程,执行任务时会略有不同,结果如上所示。