提交任務的方式一共有兩種,分別是execute和submit。
今天就來介紹他們兩個以及他們的區別。
首先來看execute,該方法位於executor中,作用是向線程中提交runnable任務。
runnable任務大家都知道,他是一個無返回值的任務,也就是他執行完是沒有返回結果給你的,所以execute只適合提交無返回值的任務。
如果你的任務是有返回結果的,那么你就得創建callable任務,它是一個有返回值的任務。
callable任務執行完會將任務執行結果封裝到future對象中,
然后反饋給調用者。調用者在通過future對象獲取結果。
待會介紹submit方法時演示這些操作。
回到execute方法本身,提交的任務如果被拒絕,則拋出任務拒絕異常,提交的任務不能為null,否則會拋出空指針異常。
execute
接下來我們就來演示execute的方法,既然要提交一個任務,我們就先編寫一個任務。
創建任務
任務內容是輸出當前線程名稱,接下來我們來執行該任務。
創建線程池並調用
首先將任務創建出來,然后創建一個線程池,這里我們就以單個線程的線程池為例,接着調用execute方法向線程池中提交該任務,
最后調用shutdown方法關閉線程池。
至此方法編寫完成,整個例子也編寫完成執行程序觀察執行結果。
從執行結果來看,程序只輸出了一個線程名稱。
submit
看完了execute,再來看看submit,該方法位於executorservice接口中,一共有三個submit方法,他們作用稍有不同,
這里我將三個方法的作用分別列舉出來,他們的返回值類型都是future類型,而且都帶泛型。任務執行結果就封裝在future對象里面。
future是一個接口,該接口定義了與任務執行相關的功能,這是future的UML類。
圖,從中我們可以看到它一共有五個可用的方法,這五個方法的作用如圖所示,大家簡單的看一下,這里就不展開講了,下一節我們將詳細介紹future。
回到submit方法本身,我們介紹第一個submit方法,它的作用是提交runnable任務,Submit方法也可以提交任務方法返回一個future對象都無返回值了,為什么還要返回future對象?是因為future除了獲取任務執行結果以外,
還可以觀察任務是否執行完畢以及取消任務等等操作。所以future對象你可以選擇接收,您可以選擇不接收。
submit無返回
接下來我們來演示該方法,還是沿用之前的例子,將execute的方法改為submit方法。submit方法返回一個future對象,這里我們選擇先接收返回值,注意泛型當中的問號是不確定類型,你就全當obj的類型來理解就好了,調用future的get方法。可以獲取到任務執行結果,有異常拋出使用try---catch,將其捕獲輸出任務執行結果,
寫上finally代碼塊,將關閉線程池的操作放入finally代碼塊中,這樣程序無論是正常執行完畢還是發生異常,都將關閉線程池。
例子編寫完成執行程序,觀察執行結果。
從執行結果來看,程序輸出線程名稱和null是我們獲取的任務執行結果,因為我們提交的是無返回值任務,所以結果為null。如果我們非要給無返回值任務一個結果可不可以?那也是可以的。
submit固定返回
這就是我們要介紹的第二個submit方法.
它的作用就是提交一個runnable任務給線程池,
並且還可以附帶一個執行結果。別的任務都是執行完才知道結果的,這個submit方法是執行任務之前都已經知道了任務執行結果,所以它只適用於執行任務的同時還要附帶一個參數的場景,該方法依然是返回一個Futurn對象,像這個Futurn對象里面封裝的結果就是我們剛剛傳遞的第二個參數。接下來我們來演示該方法,還是沿用之前的例子,修改提交任務的代碼,調用兩個參數的submit方法。第二個參數可以傳些什么?你可以傳對象,你也可以傳數字,還可以傳字符串,布爾類型也能傳。
我們就以字符串為例好了,傳遞一句任務完成,在任務完成以后打印出來,此時future的類型不再是不確定的類型,而是字符串string類型。獲取任務執行結果的代碼也需要修改,將object類型改為string類型,因為我們的任務執行結果是string類型。
例子改寫完成執行改寫后的例子,觀察執行結果,從執行結果來看,程序輸出任務完成符合預期。
submit自定義返回
再介紹最后一個submit的方法,它的作用是提交的任務,也就是有返回值的任務方法,返回一個future。
接下來我們來演示該方法,重新編寫一個需要結果的任務resulttask任務內容是計算一加一的值,實現callable接口,一加一的結果是整形,所以泛型的類型是Integer,重寫call方法返回一加一的計算結果。至此任務編寫完成。
執行任務的代碼還是沿用之前的,只不過需要將task任務改為剛剛編寫的resulttask任務。接下來提交任務的代碼也需要修改,將第二個參數刪掉,只保留第一個參數。future泛型的類型由string改為integer,
因為任務執行結果就是integer類型,獲取任務執行結果的訪問值類型也得改,將string改為integer。
例子改寫完成執行。改寫后的程序觀察執行結果,從執行結果來看,程序輸出二,符合預期。
區別
兩種提交任務的方式看完了,再來看看它們的區別。從位置說起,execute的方法位於executor的接口中。submit方法位於executorservice接口中.
再來說說提交任務的類別,execute的方法只支持提交任務,而submit方法既支持runnable任務又支持callable任務。
返回值類型方面,Execute方法無返回值,而submit方法返回future對象。這次execute方法和submit方法的區別介紹完了。
總結
最后總結一下本節內容。本節介紹了提交任務的兩種方式,Execute和submit,他們各自支持的任務如圖所示,這里就不再贅述了。在實際開發中,Submit這種方式用的比較多,我一般也在用。