线程池(6)-submit与execute区别
在线程池里提交任务经常见到submit与execute,如何选择,傻傻分不清楚。那么他们俩有什么区别,使用场景是什么?这篇博客将会介绍。
1.方法定义
void execute(Runnable command); Future<T> submit(Callable<T> task); Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);
2.使用上的区别
2.1execute没有返回值(Future)
2.2执行结果(future.get)
2.3submit可以捕获runnable里的异常
3.示例
3.1使用Future判断任务是否执行完,5s后任务超时就停止任务。
public class ThreadPoolSubmitFuture { static class MyRunnable implements Runnable { private String jobName; private Thread nowThread; MyRunnable(String jobName) { this.jobName = jobName; } public void setInterrupted() { nowThread.interrupt(); } @Override public void run() { nowThread = Thread.currentThread(); try { while (true) { Thread.sleep(1000); // 写了sleep就不用再判断isInterrupted()了 System.err.println("当前线程:" + Thread.currentThread().getName() + " 当前任务:" + jobName); } } catch (InterruptedException e) { System.err.println("当前线程:" + Thread.currentThread().getName() + " 当前任务:" + jobName + "马上停止"); e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { ExecutorService es = Executors.newFixedThreadPool(2, new MyThreadFactory()); MyRunnable job1 = new MyRunnable("job-1"); Future<?> f = es.submit(job1); try { f.get(5, TimeUnit.SECONDS); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { // 超时停止 job1.setInterrupted(); e.printStackTrace(); } try { f.get(); } catch (ExecutionException e) { e.printStackTrace(); } } }
3.2执行结果
MyRunnable不变
public static void main(String[] args) throws InterruptedException { ExecutorService es = Executors.newFixedThreadPool(2, new MyThreadFactory()); MyRunnable job1 = new MyRunnable("job-1"); Future<String> f = es.submit(job1, "我执行完了"); try { f.get(5, TimeUnit.SECONDS); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { // 超时停止 job1.setInterrupted(); e.printStackTrace(); } try { String rs = f.get(); System.err.println("job-1执行完后,说了啥:" + rs); } catch (ExecutionException e) { e.printStackTrace(); } }
3.3捕获异常
在Runnale中可以抛出RuntimeException,不可以抛出Exception
public class ThreadPoolSubmitFutureException { static class MyRunnable implements Runnable { private String jobName; private Thread nowThread; MyRunnable(String jobName) { this.jobName = jobName; } public void setInterrupted() { nowThread.interrupt(); } @Override public void run() { nowThread = Thread.currentThread(); try { while (true) { Thread.sleep(1000); // 写了sleep就不用再判断isInterrupted()了 System.err.println("当前线程:" + Thread.currentThread().getName() + " 当前任务:" + jobName); } } catch (InterruptedException e) { System.err.println("当前线程:" + Thread.currentThread().getName() + " 当前任务:" + jobName + "马上停止"); e.printStackTrace(); throw new RuntimeException("当前线程:" + Thread.currentThread().getName() + " 当前任务:" + jobName + " 我出现异常了"); } } } public static void main(String[] args) throws InterruptedException { ExecutorService es = Executors.newFixedThreadPool(2, new MyThreadFactory()); MyRunnable job1 = new MyRunnable("job-1"); Future<?> f = es.submit(job1); try { f.get(5, TimeUnit.SECONDS); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { // 超时停止 job1.setInterrupted(); e.printStackTrace(); } try { f.get(); } catch (ExecutionException e) { e.printStackTrace(); } catch (RuntimeException re) { re.printStackTrace(); } } }
3.4异常不捕获会怎么样
execute会导致执行的线程销毁,线程池会重新创建一个新的线程来执行其他任务,这样就会导致线程池的线程得不到复用。
submit不会导致执行的线程销毁,但是你不future.get()你永远不会知道这个异常。
4.总结
4.1如果任务有返回值,有抛出异常,使用submit
4.2如果要判断任务执行完,以便进行其他处理,使用submit
4.3使用submit抛出的异常,不捕获将不会知道有这个异常
posted on 2019-10-29 14:08 SmilingEye 阅读(1062) 评论(0) 编辑 收藏 举报