转载:线程池
线程提交的两种方式
ExecutorService poll3 = Executors.newCachedThreadPool();for (int i = 0; i < 2; i++) {poll3.execute(new TargetTask());poll3.submit(new TargetTask());}
- execute方法
void execute(Runnable command)
: Executor接口中的方法 - submit方法
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
这3个submit方法都是ExecutorService接口中的方法(ExecutorService接口 是Executor接口的子类)
区别
- execute 方法只能接收 Runnable 类型的参数, submit 方法可以接收 Runnable 和 Callable 两种类型的参数
- execute 方法没有返回值,submit 方法有返回值(原因是Callable 类型任务有返回值,Runnable 类型任务没有返回值)
- submit()方便子线程的异常处理
@Slf4j
public class ExecutorsTest {static class TargetTask implements Runnable {public static final int SLEEP_GAP = 1000;// AtomicInteger 提供了一种线程安全的方式来对整数进行操作。它可以保证多个线程同时对同一个AtomicInteger对象进行操作时,不会出现数据竞争和不一致的情况static AtomicInteger taskNo = new AtomicInteger(0);String taskName;@Overridepublic void run() {log.info(taskName + "is running ...");try {Thread.sleep(SLEEP_GAP);} catch (Exception e) {log.error(taskName + "running error !");e.printStackTrace();}log.info(taskName + "is end ...");}TargetTask() {taskName = "task_" + taskNo;taskNo.incrementAndGet();}}static class TargetTaskWithError extends TargetTask {public void run() {super.run();//执行父类的run方法// 强行抛出异常throw new RuntimeException("Error from " + taskName);}}public static void main(String[] args) throws InterruptedException {ExecutorService poll6 = Executors.newFixedThreadPool(3);// execute 方式不关心任务执行的结果,没有返回值,不能处理异常try{poll6.execute(new TargetTaskWithError());}catch (Exception e){log.error("task has Exception !");e.printStackTrace();}// submit 方式有返回值,方便处理异常
// Future future = poll6.submit(new TargetTaskWithError());
// try {
// if (null == future.get()) {
// log.info(" task no Exception !");
// }
// } catch (Exception e) {
// log.error("task has Exception !");
// e.printStackTrace();
// }poll6.shutdown();}
}
如图:
使用 submit 向线程池提交任务可以处理异常,打印了task has Exception !
使用 execute 向线程池提交任务不能处理异常,未打印了task has Exception !