线程池(百度百科)
线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池 维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量
Java中的线程池种类
1.单线程的线程池 newSingleThreadExecutor 单线程线程池只有一个线程工作串行执行所有工作
代码示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class pool {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
pool.execute(() -> {
System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
});
}
}
}
运行结果:从运行结果来看 只有一个线程在运行
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-1
2.固定大小的线程池 newFixedThreadPool 就像一个固定的容器,每次提交一个任务就去创建一个线程去执行,直到达到线程池的最大大小,线程池的大小达到最大值后就不会变
代码示例 首先创建一个大小为5的线程池 执行5个任务
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class pool {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
pool.execute(() -> {
System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
});
}
}
}
运行结果:可以看到一直达到线程池的最大大小
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-5
Hello World 我是线程pool-1-thread-4
Hello World 我是线程pool-1-thread-3
接下来我们放10个任务进去
for (int i = 0; i < 10; i++) {
pool.execute(() -> {
System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
});
}
结果:可以看到线程池达到最大容量后 随机分配线程去执行了任务
Hello World 我是线程pool-1-thread-3
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-3
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-3
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-5
Hello World 我是线程pool-1-thread-4
Hello World 我是线程pool-1-thread-2
3.定时及可以周期性执行任务的线程池newScheduledThreadPool,此线程池也有固定的大小,但是执行任务的时候并不是一直执行任务,直到线程池的最大大小
代码示例:创建一个大小为5的线程,执行10个任务,并且3秒后执行
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class pool {
public static void main(String[] args) {
ExecutorService pool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
((ScheduledExecutorService) pool).schedule(() -> {
System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
},3,TimeUnit.SECONDS);
}
}
}
结果:可以看到在3秒后线程池开始执行任务,并且也是随机分配线程去执行任务
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-5
Hello World 我是线程pool-1-thread-1
4.可缓存的线程池 newCachedThreadPool 可以看做是一个可变大小的线程池,当线程池的大小超过需要执行任务的数量时,会回收部分线程,而当任务数量增加时,又会增加新的线程去执行任务。
代码示例:创建线程池去执行5个任务
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class pool {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
pool.execute(() -> {
System.out.println("Hello World"+" "+"我是线程"+Thread.currentThread().getName() );
});
}
}
}
结果
Hello World 我是线程pool-1-thread-3
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-5
Hello World 我是线程pool-1-thread-4
当我们放10个任务进去的时候
执行结果
Hello World 我是线程pool-1-thread-1
Hello World 我是线程pool-1-thread-5
Hello World 我是线程pool-1-thread-2
Hello World 我是线程pool-1-thread-6
Hello World 我是线程pool-1-thread-4
Hello World 我是线程pool-1-thread-8
Hello World 我是线程pool-1-thread-9
Hello World 我是线程pool-1-thread-10
Hello World 我是线程pool-1-thread-3
Hello World 我是线程pool-1-thread-7
源码分析:可以看到线程池的初始大小为0,但允许线程池数量为最大
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}