一、线程池概念:
1. 什么是线程池?
jdk1.5之后java.util.concurrent.Executors提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池。线程池是事先创建若干个可执行的线程放入一个池(容器)中。在需要的时候直接从池中获取线程而不用自行创建,使用完毕不需要销毁线程而是放回到池(容器)中。从而减少创建和销毁线程对象的开销。
2.为什么使用线程池?
在前面使用线程的例子中,如果你的idea安装了阿里编码规约插件可能已经注意到idea提示不要显式创建线程,请使用线程池。,这说明线程池比直接创建线程有优势,否则编码规约不会警告我们。线程池具体优势总结如下:
- 降低系统资源消耗,通过重用已存在的线程,降低线程的创建和销毁造成的消耗;
- 提高系统响应速度,当有任务到达时,通过复用已存在线程,无需等待新线程创建便可以立即执行;
- 方便线程并发数的管理,因为线程如果无限制的创建,可能会导致内存占用过多出现OOM,cpu过度切换也会造成性能降低
- 提供更强大的功能,延时定时线程池
下面我们通过循环1w次,开启1w线程打印i值,来简单对比下线程池和线程的性能。是否如上面提到的有那么多优势:
public class ExecutorsTest {
static List<Integer> list = new ArrayList<>();
public static void threads() throws InterruptedException {
for (int i = 0; i < 10_000; i++) {
int tmp = i;
Thread thread = new Thread(() -> {
list.add(tmp);
});
// for循环1000次,开启1000个线程
thread.start();
thread.join();
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
try {
threads();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
Optional.of("1000个线程执行耗时->" + (end - start)).ifPresent(System.out::println);
}
}
****************************************************
1000个线程执行耗时->2055
通过Executors.newSingleThreadExecutor():创建一个单线程化的线程池。
public class ExecutorsTest {
static List<Integer> list = new ArrayList<>();
public static void threads() throws InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10_000; i++) {
int tmp = i;
executorService.execute(new Runnable() {
@Override
public void run() {
list.add(tmp);
}
});
}
executorService.shutdown();
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
try {
threads();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
Optional.of("线程池执行耗时->" + (end - start)).ifPresent(System.out::println);
}
}
*****************************
线程池执行耗时->14
通过代码对比,很明显线程池和线程之间的性能差距。newSingleThreadExecutor线程池限制系统中执行线程的数量(只会有一个线程执行)。减少了浪费了系统资源,cpu调度和切换带来的时间损耗。
网友评论