为什么要使用线程池?
JDK中基于Executors 提供了很多线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
threadPool.execute(() -> {
System.out.println("1号任务" + Thread.currentThread().getName() + System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
threadPool.execute(() -> {
System.out.println("2号任务" + Thread.currentThread().getName() + System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
threadPool.execute(() -> {
System.out.println("3号任务" + Thread.currentThread().getName() + System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
public static ExecutorService newSingleThreadExecutor() {
// 在内部依然是构建了ThreadPoolExecutor,设置线程个数为1。当任务投递过来后,第一个任务会被工作线程处理,后续的任务会被扔到阻塞队列中,投递到阻塞队列中任务的顺序就是工作线程处理的顺序
// 当前线程池可以用作顺序处理的一些业务中
return new Executors.FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
static class FinalizableDelegatedExecutorService extends Executors.DelegatedExecutorService {
// 线程池的使用没有区别,跟正常的ThreadPoolExecutor没区别
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
// finalize是当前对象被GC干掉之前要执行的方法
// 当前FinalizableDelegatedExecutorService的目的是为了在当前线程池被GC回收之前,可以执行shutdown,shutdown方法是将当前线程池停止,并且干掉工作线程
// 但是不能基于这种方式保证线程池一定会执行shutdown,finalize在执行时,是守护线程,这种线程无法保证一定可以执行完毕。
// 在使用线程池时,如果线程池是基于一个业务构建的,在使用完毕之后,一定要手动执行shutdown,否则会造成JVM中一堆线程
protected void finalize() {
super.shutdown();
}
}
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "," + "111");
});
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "," + "222");
});
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "," + "333");
});
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "," + "444");
});
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 1; i <= 200; i++) {
final int x = i;
threadPool.execute(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + x);
});
}
}
// 基于这个方法可以看到,构建的是 ScheduledThreadPoolExecutor
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor
implements ScheduledExecutorService {
// ...
}
public static void main(String[] args) {
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10);
// // 正常执行
// threadPool.execute(() -> {
// System.out.println(Thread.currentThread().getName() + ": 1");
// });
//
// // 延迟执行,执行当前任务延迟5s后执行
// threadPool.schedule(() -> {
// System.out.println(Thread.currentThread().getName() + ": 2");
// }, 5, TimeUnit.SECONDS);
//
// // 周期执行,当前任务第一次延迟2s执行,然后每1s执行一次
// // 这个方法在计算下次执行时间时,是从任务刚刚开始时就计算
// threadPool.scheduleAtFixedRate(() -> {
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + ": 3");
// }, 2, 1, TimeUnit.SECONDS);
threadPool.scheduleWithFixedDelay(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": 4");
}, 2, 1, TimeUnit.SECONDS);
}
举个例子:来一个比较大的数组,里面存满值,计算总和
/** 非常大的数组 */
static int[] nums = new int[1_000_000_000];
// 填充值
static{
for (int i = 0; i < nums.length; i++) {
nums[i] = (int) ((Math.random()) * 1000);
}
}
public static void main(String[] args) {
// ===================单线程累加10亿数据================================
System.out.println("单线程计算数组总和!");
long start = System.nanoTime();
int sum = 0;
for (int num : nums) {
sum += num;
}
long end = System.nanoTime();
System.out.println("单线程运算结果为:" + sum + ",计算时间为:" + (end - start));
}
/**
* 非常大的数组
*/
static int[] nums = new int[1_000_000_000];
// 填充值
static {
for (int i = 0; i < nums.length; i++) {
nums[i] = (int) ((Math.random()) * 1000);
}
}
public static void main(String[] args) {
// ===================单线程累加10亿数据================================
System.out.println("单线程计算数组总和!");
long start = System.nanoTime