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抛出的异常,不捕获将不会知道有这个异常

  • 相关阅读:
    Word 转换为 PDf 的技术方案
    [转载]sql server 常用存储过程
    Redmine 初体验
    Quartz.net Tutorial Lesson 1
    [转载]sql server TSQL 区分字符串大小写 的两种方法
    [原创]sql server inner join 效率测试
    java实现树的一般操作
    【转】Mybatis中进行批量更新
    【转载】单例模式的7种写法(整合自两篇文章)
    mybtis批量insert传入参数为list
  • 原文地址:https://www.cnblogs.com/SmilingEye/p/11758406.html
Copyright © 2011-2022 走看看