自动创建线程池
直接调用Java 内置已经封装好了的线程池
FixedThreadPool
创建一个固定线程数量的线程池, 内部使用无界队列 LinkedBlockingQueue
public class FixedThreadPool {
public static void main(String[] args) {
ExecutorService threadPool= Executors.newFixedThreadPool(4);
for (int i = 0; i < 100; i++) {
threadPool.execute(new SimpleTask1());
}
}
}
public class SimpleTask1 implements Runnable {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
运行 main 方法, 部分输出结果:
pool-1-thread-3
pool-1-thread-1
pool-1-thread-2
pool-1-thread-4
pool-1-thread-4
pool-1-thread-3
pool-1-thread-1
pool-1-thread-2
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-4
pool-1-thread-4
pool-1-thread-1
可以看出, 无论我们往线程池里面加入多少任务, 都有且只有4个线程, 不会出现5个线程.
回想 FiexedThreadPool 的两个特性: 固定线程数量 和 无界队列. 我们很容易想到这类线程池的缺点. 假设每个任务的处理时间较长, 则未处理的任务则会一直存在于队列里面, 队列总会溢出的.
我们稍微修改一下 FiexedThreadPool 和 SimpleTask1. 将每一个任务的时间设置的足够长, 将提交任务的数量设置的很多.
public class FixedThreadPool {
public static void main(String[] args) {
ExecutorService threadPool= Executors.newFixedThreadPool(4);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
threadPool.execute(new SimpleTask1());
}
}
}
public class SimpleTask1 implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
运行结果:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
抛出 OutOfMemoryError
SingleThreadExecutor
创建一个只有一个线程的线程池, 内部使用无界队列 LinkedBlockingQueue,
public class SingleThreadExecutor {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 100; i++) {
threadPool.execute(new SimpleTask2());
}
}
}
public class SimpleTask2 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
运行结果
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1
可以看出永远只有一个线程在运行.
同样的当请求堆积的时候, 会占用大量内存, 也可能导致 OutOfMemoryError, 这里就不演示了.
CachedThreadPool
CachedThreadPool 的 corePoolSize 为0 ,maxPoolSize 无限大(最大整型), 使用SynchronousQueue 直接交接队列. 一定时间后(默认60s), 空闲的线程会被回收
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService threadPool= Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
System.out.println(i);
threadPool.execute(new SimpleTask2());
}
}
}
public class SimpleTask2 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
部分运行结果:
pool-1-thread-112
pool-1-thread-111
pool-1-thread-112
pool-1-thread-39
pool-1-thread-60
pool-1-thread-14
pool-1-thread-64
pool-1-thread-14
pool-1-thread-64
可以看出, 最多时候有100多个线程, 但随后这些线程又被回收了, 不需要这么多.
同样的, 因为 maxPoolSize 被设置为了 Integer.MAX_VALUE, 可能会创建数量非常多的线程, 导致 OutOfMemoryError.
ScheduledThreadPool
corePoolSize 为0, maxPoolSize 为 Integer.MAX_VALUE, 使用SynchronousQueue 直接交接队列
public class ScheduledThreadPool {
public static void main(String[] args) {
ScheduledExecutorService threadPool= Executors.newScheduledThreadPool(10);
//用法1, 延迟5秒运行线程池
threadPool.schedule(new SimpleTask2(),5, TimeUnit.SECONDS);
//用法2, 延迟1秒运行线程池, 以后每隔三秒处理一个任务
threadPool.scheduleAtFixedRate(new SimpleTask2(),1,3,TimeUnit.SECONDS);
}
}
public class SimpleTask2 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
总结一下
corePoolSize
自定义
0
自定义
1
maxPoolSize
自定义
Integer.MAX_VALUE
Integer.MAX_VALUE
1
keepAliveTime
0
60s
0
0
workQueue
LinkedBlockingQueue
SynchronousQueue
DelayedWorkQueue
LinkedBlockingQueue
DelayedWorkQueue 延迟队列, 其底层是一个 堆.
Last updated