線程池提交任務的兩種方式:execute與submit的區別


Java中的線程池在進行任務提交時,有兩種方式:execute和submit方法。

 

一、execute和submit的區別

  • execute只能提交Runnable類型的任務,無返回值。submit既可以提交Runnable類型的任務,也可以提交Callable類型的任務,會有一個類型為Future的返回值,但當任務類型為Runnable時,返回值為null。
  • execute在執行任務時,如果遇到異常會直接拋出,而submit不會直接拋出,只有在使用Future的get方法獲取返回值時,才會拋出異常。

測試代碼:

package com.javaBase.LineDistancePond;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 〈一句話功能簡述〉;
 * 〈execute與submit的區別〉
 *
 * @author jxx
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class TestThreadPoolBegin {

    public static void main(String[] args) throws Exception{
        ExecutorService es = Executors.newSingleThreadExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable線程處理開始...");
                int a = 0;
                int b = 3;
                System.out.println("除以0的結果為:" + b/a);
                System.out.println("Runnable線程處理結束...");
            }
        };
        es.execute(runnable);
        es.shutdown();
    }
}

執行結果:

Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
Runnable線程處理開始...
    at com.javaBase.LineDistancePond.TestThreadPoolBegin$1.run(TestThreadPoolBegin.java:24)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Process finished with exit code 0
package com.javaBase.LineDistancePond;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 〈一句話功能簡述〉;
 * 〈execute與submit的區別〉
 *
 * @author jxx
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class TestThreadPoolBegin {

    public static void main(String[] args) throws Exception{
        ExecutorService es = Executors.newSingleThreadExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable線程處理開始...");
                int a = 0;
                int b = 3;
                System.out.println("除以0的結果為:" + b/a);
                System.out.println("Runnable線程處理結束...");
            }
        };
        es.submit(runnable);
        es.shutdown();
    }
}

執行結果:

Runnable線程處理開始...

Process finished with exit code 0
package com.javaBase.LineDistancePond;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 〈一句話功能簡述〉;
 * 〈execute與submit的區別〉
 *
 * @author jxx
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class TestThreadPoolBegin {

    public static void main(String[] args) throws Exception{
        ExecutorService es = Executors.newSingleThreadExecutor();
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("線程處理開始...");
                int a = 0;
                int b = 3;
                System.out.println("除以0的結果為:" + b/a);
                System.out.println("線程處理結束...");
                return "0";
            }
        };
        Future<String> future = es.submit(callable);
        System.out.println("任務執行完成,結果為:" + future.get());
    }
}

執行結果:

Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at com.javaBase.LineDistancePond.TestThreadPoolBegin.main(TestThreadPoolBegin.java:32)
Caused by: java.lang.ArithmeticException: / by zero
    at com.javaBase.LineDistancePond.TestThreadPoolBegin$1.call(TestThreadPoolBegin.java:26)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
線程處理開始...

二、submit的get方法

  future的get方法在未獲得返回值之前會一直阻塞,我們可以使用future的isDone方法判斷任務是否執行完成,然后再決定是否get,因此上述代碼我們可以優化如下:

package com.javaBase.LineDistancePond;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 〈一句話功能簡述〉;
 * 〈execute與submit的區別〉
 *
 * @author jxx
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class TestThreadPoolBegin {

    public static void main(String[] args) throws Exception{
        ExecutorService es = Executors.newSingleThreadExecutor();
        Callable callable = new Callable() {
            @Override
            public String call() throws Exception {
                System.out.println("線程處理開始...");
                int a = 2;
                int b = 3;
                System.out.println("3/2的結果為:" + b/a);
                System.out.println("線程處理結束...");
                return "0";
            }
        };
        Future<String> future = es.submit(callable);
        while(true) {
            //idDone:如果任務已完成,則返回 true。 可能由於正常終止、異常或取消而完成,在所有這些情況中,此方法都將返回 true。
            if(future.isDone()) {
                System.out.println("任務執行完成:" + future.get());
                break;
            }
        }
        es.shutdown();
    }
}

執行結果:

線程處理開始...
3/2的結果為:1
線程處理結束...
線程執行完成:0

Process finished with exit code 1

 

 


免責聲明!

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



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