線程池(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拋出的異常,不捕獲將不會知道有這個異常

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM