侧边栏

线程池(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  阅读(934)  评论(0编辑  收藏  举报

导航