文章目录
在上一篇博客 【Java 并发编程】线程池机制 ( 测试线程开销 | 启动线程分析 | 用户态 | 内核态 | 用户线程 | 内核线程 | 轻量级进程 ) 中 , 分析了线程的开销 ;
本篇博客中使用线程池改造该示例并进行分析 ;
一、线程池示例
创建 10 10 10 万线程 , 需要 10992 10992 10992 ms ; 使用线程池启动 10 10 10 万线程 , 仅需要 26 26 26 ms ;
线程池的效率比线程高几个数量级 ;
线程池示例 :
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
/**
* 线程中对该值进行累加操作
*/
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
// 记录程序开始执行时间
long startTime = System.currentTimeMillis();
// 线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 每次线程执行完毕, 计数 -1 , 当计数减到 0 之后, 才能解除阻塞
CountDownLatch countDownLatch = new CountDownLatch(100000);
// 创建 10 万个线程, 开启线程后, 向集合中添加一个元素
for (int i = 0; i < 100000; i ++) {
executorService.execute(new Runnable() {
@Override
public void run() {
count ++;
// 计数 -1
countDownLatch.countDown();
}
});
}
// 阻塞等待计数 -1, 直到 10000 个线程执行完毕
// 使用这种方式确定所有线程执行完毕
countDownLatch.await();
// 执行完毕后, 停掉线程池, 否则程序不会退出
executorService.shutdown();
// 记录程序执行结束时间
long endTime = System.currentTimeMillis();
// 打印消耗的时间
System.out.println("耗时 : " + ( endTime - startTime ) + " ms , 最终 count = " + count);
}
}
执行结果 : 原来使用线程需要 10992 10992 10992 ms 时间 , 使用线程池后 , 仅需要 26 26 26 ms , 这效率提升了好几个数量级 ;
等待线程执行结束 , 直接调用 Thread.join()
方法 , 等待线程池结束 , 借助 CountDownLatch
通过线程计数来确定线程是否执行完毕 ;
调用 ExecutorService executorService = Executors.newSingleThreadExecutor()
创建线程池 , 创建的是 FinalizableDelegatedExecutorService 线程池 ;
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
二、newCachedThreadPool 线程池示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executorService1 = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i ++) {
executorService1.execute(new Task(i));
}
}
static class Task implements Runnable {
/**
* 记录线程的索引 0 ~ 99
*/
private int i = 0;
public Task(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println("线程 ID : " + Thread.currentThread().getName() + " , 线程索引 : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果 : 该线程池中创建了 100 100 100 个线程 , 执行 100 100 100 个任务 ;
三、newFixedThreadPool 线程池示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executorService2 = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i ++) {
executorService2.execute(new Task(i));
}
}
static class Task implements Runnable {
/**
* 记录线程的索引 0 ~ 99
*/
private int i = 0;
public Task(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println("线程 ID : " + Thread.currentThread().getName() + " , 线程索引 : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果 : 该线程池中创建了 10 10 10 个线程 , 执行 100 100 100 个任务 ;
三、newSingleThreadExecutor 线程池示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executorService3 = Executors.newSingleThreadExecutor();
for (int i = 0; i < 100; i ++) {
executorService3.execute(new Task(i));
}
}
static class Task implements Runnable {
/**
* 记录线程的索引 0 ~ 99
*/
private int i = 0;
public Task(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println("线程 ID : " + Thread.currentThread().getName() + " , 线程索引 : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果 : 该线程池中创建了 1 1 1 个线程 , 执行 100 100 100 个任务 ;