Java 通过 Executors 提供四种线程池, 例如:
- newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
线程池接口 ExecutorService
- ExecutorService: 真正的线程池接口。
- ScheduledExecutorService: 能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。
- ThreadPoolExecutor: ExecutorService的默认实现。
- ScheduledThreadPoolExecutor: 继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。
public class ExecutorServiceTest {
public static void main(String[] args) {
// Returns the number of processors available to the Java virtual
// machine
// int count = Runtime.getRuntime().availableProcessors();
// System.out.println(count);
// 1. 可缓存线程池
// newCachedThreadPoolMe();
// 2. 定长线程池
// newFixedThreadPoolMe();
// 3. 定长线程池,支持定时及周期性任务执行
// newScheduleThreadPoolMe();
// 4. 单线程化的线程池
// newSingleThreadExecutorMe();
test();
}
// newCachedThreadPool 可缓存线程池
public static void newCachedThreadPoolMe() {
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; ++i) {
final int index = i;
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
}
pool.shutdown();
}
// newFixedThreadPool 定长线程池
public static void newFixedThreadPoolMe() {
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 100; ++i) {
final int index = i;
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
}
pool.shutdown();
}
// newScheduleThreadPool 定长线程池,支持定时及周期性任务执行
public static void newScheduleThreadPoolMe() {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 100; ++i) {
final int index = i;
pool.schedule(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
}, 10, TimeUnit.SECONDS);
}
pool.shutdown();
}
// newSingleThreadExecutor 单线程化的线程池
public static void newSingleThreadExecutorMe() {
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 100; ++i) {
final int index = i;
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
}
pool.shutdown();
}
/**
* 异常处理测试
*/
public static void test() {
ExecutorService pool = Executors.newSingleThreadExecutor();
// pool.execute(new Runnable() {
// @Override
// public void run() {
// int i = 10 / 0;
// }
// });
Future<Boolean> future = pool.submit(new Callable<Boolean>() {
@Override
public Boolean call() {
int i = 10 / 0;
return true;
}
});
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
pool.shutdown();
}
}
通过 execute 提交的任务,才能将它抛出的异常交给未捕获异常处理器,而通过 submit 提交的任务,无论是抛出的未检查异常还是已检查异常,都将被认为是任务返回状态的一部分。如果一个由 submit 提交的任务由于抛出了异常而结束,那么这个异常将被 future.get() 封装在 ExecutionException 中重新抛出。