zoukankan      html  css  js  c++  java
  • 线程池(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抛出的异常,不捕获将不会知道有这个异常

  • 相关阅读:
    bzoj 1053: [HAOI2007]反素数ant 搜索
    bzoj 1040: [ZJOI2008]骑士 環套樹DP
    对主席树的一些理解
    POJ 2777 Count Color【线段树】
    POJ 2420 A Star not a Tree?【爬山法】
    生物遗传学 整理人PYJ (恋_紫花地丁)
    POJ3321Apple Tree【dfs 树状数组】
    POJ1450:Gridland 【杂题】
    POJ 1088 滑雪【记忆化搜索】
    Poj3253:Fence Repair 【贪心 堆】
  • 原文地址:https://www.cnblogs.com/SmilingEye/p/11758406.html
Copyright © 2011-2022 走看看