因為之前一直是用的execute方法,最近有個情況需要用到submit方法,所以研究了下。
他們的區別:
1、execut()可以添加一個Runable任務,submit()不僅可以添加Runable任務還可以添加Callable任務。
2、execut()沒有返回值,而submit()在添加Callable任務時會有返回值(再添加Runable任務時也有,不過無意義),可以通過返回值來查看線程執行的情況。
3、如果發生異常submit()可以通過捕獲Future.get拋出的異常,而execute()會終止這個線程。
在Java5之后,並發線程這塊發生了根本的變化,最重要的莫過於新的啟動、調度、管理線程的一大堆API了。在Java5以后,通過Executor來啟動線程比用Thread的start()更好。在新特征中,可以很容易控制線程的啟動、執行和關閉過程,還可以很容易使用線程池的特性。
ExecutorService executorService = Executors.newCachedThreadPool(); ExecutorService executorService = Executors.newFixedThreadPool(3); ExecutorService executorService = Executors.newSingleThreadExecutor();
2、將任務添加到線程去執行
三、關閉執行服務對象
四、綜合實例
package concurrent; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
publicclass TestCachedThreadPool { publicstaticvoid main(String[] args) { // ExecutorService executorService = Executors.newCachedThreadPool(); ExecutorService executorService = Executors.newFixedThreadPool(5); // ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 5; i++){ executorService.execute(new TestRunnable()); System.out.println("************* a" + i + " *************"); } executorService.shutdown(); } }
class TestRunnable implements Runnable { publicvoid run() { System.out.println(Thread.currentThread().getName() + "線程被調用了。"); while (true) { try { Thread.sleep(5000); System.out.println(Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
運行結果:
************* a0 *************
************* a1 *************
pool-1-thread-2線程被調用了。
************* a2 *************
pool-1-thread-3線程被調用了。
pool-1-thread-1線程被調用了。
************* a3 *************
************* a4 *************
pool-1-thread-4線程被調用了。
pool-1-thread-5線程被調用了。
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-5
pool-1-thread-4
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-5
pool-1-thread-4
......
五、獲取任務的執行的返回值
當將一個Callable的對象傳遞給ExecutorService的submit方法,則該call方法自動在一個線程上執行,並且會返回執行結果Future對象。同樣,將Runnable的對象傳遞給ExecutorService的submit方法,則該run方法自動在一個線程上執行,並且會返回執行結果Future對象,但是在該Future對象上調用get方法,將返回null。
下面看個例子:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; /** * Callable接口測試 */ publicclass CallableDemo { publicstaticvoid main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); List<Future<String>> resultList = new ArrayList<Future<String>>(); //創建10個任務並執行 for (int i = 0; i < 10; i++) { //使用ExecutorService執行Callable類型的任務,並將結果保存在future變量中 Future<String> future = executorService.submit(new TaskWithResult(i)); //將任務執行結果存儲到List中 resultList.add(future); } //遍歷任務的結果 for (Future<String> fs : resultList) { try { System.out.println(fs.get()); //打印各個線程(任務)執行的結果 } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } finally { //啟動一次順序關閉,執行以前提交的任務,但不接受新任務。如果已經關閉,則調用沒有其他作用。 executorService.shutdown(); } } } } class TaskWithResult implements Callable<String> { privateint id; public TaskWithResult(int id) { this.id = id; } /** * 任務的具體過程,一旦任務傳給ExecutorService的submit方法,則該方法自動在一個線程上執行。 * * @return * @throws Exception */ public String call() throws Exception { System.out.println("call()方法被自動調用,干活!!!" + Thread.currentThread().getName()); //一個模擬耗時的操作 for (int i = 999999; i > 0; i--) ; return"call()方法被自動調用,任務的結果是:" + id + "" + Thread.currentThread().getName(); } }
運行結果:
call()方法被自動調用,干活!!! pool-1-thread-3
call()方法被自動調用,干活!!! pool-1-thread-4
call()方法被自動調用,干活!!! pool-1-thread-6
call()方法被自動調用,干活!!! pool-1-thread-2
call()方法被自動調用,干活!!! pool-1-thread-5
call()方法被自動調用,任務的結果是:0 pool-1-thread-1
call()方法被自動調用,任務的結果是:1 pool-1-thread-2
call()方法被自動調用,干活!!! pool-1-thread-2
call()方法被自動調用,干活!!! pool-1-thread-6
call()方法被自動調用,干活!!! pool-1-thread-4
call()方法被自動調用,任務的結果是:2 pool-1-thread-3
call()方法被自動調用,干活!!! pool-1-thread-3
call()方法被自動調用,任務的結果是:3 pool-1-thread-4
call()方法被自動調用,任務的結果是:4 pool-1-thread-5
call()方法被自動調用,任務的結果是:5 pool-1-thread-6
call()方法被自動調用,任務的結果是:6 pool-1-thread-2
call()方法被自動調用,任務的結果是:7 pool-1-thread-6
call()方法被自動調用,任務的結果是:8 pool-1-thread-4
call()方法被自動調用,任務的結果是:9 pool-1-thread-3
Process finished with exit code 0