淺談Java獲得多線程的返回結(jié)果方式(3種)
一:Java創(chuàng)建線程方式
繼承Thread類或者實(shí)現(xiàn)Runnable接口。但是Runnable 的 run() 方法是不帶返回值的,那如果我們需要一個(gè)耗時(shí)任務(wù)在執(zhí)行完之后給予返回值,應(yīng)該怎么做呢?
第一種方法:在 Runnable 的實(shí)現(xiàn)類中設(shè)置一個(gè)變量 V,在 run 方法中將其改變?yōu)槲覀兤诖慕Y(jié)果,然后通過一個(gè) getV() 方法將這個(gè)變量返回。
package com.test.thread;import java.util.*;import sun.swing.AccumulativeRunnable;//獲得線程的返回結(jié)果方式一/* *在runnable實(shí)現(xiàn)類中設(shè)置一個(gè)變量x,在run方法中將其改變?yōu)槲覀兤诖慕Y(jié)果,然后通過一個(gè)getX()方法將這個(gè)變量返回 */public class RunnableTest { public static void main(String[] args) throws Exception { System.out.println('使用Runnable獲取返回結(jié)果'); List<Thread> workers = new ArrayList<>(10); List<RunnableAcction> tasks = new ArrayList<>(10); //創(chuàng)建10個(gè)線程,每個(gè)線程分別負(fù)責(zé)累加1-10,11-20,.........,91-100 for(int i=0;i<10;i++) { RunnableAcction task = new RunnableAcction(i*10+1,(i+1)*10); Thread work = new Thread(task,'累加器線程'+i); workers.add(work); tasks.add(task); work.start(); } int total = 0; for(int i = 0;i<workers.size();i++) { workers.get(i).join(); total += tasks.get(i).getResult(); } System.out.println('n累加的結(jié)果:'+total); } static final class RunnableAcction implements Runnable{ private int a; public RunnableAcction(int a, int b) { super(); this.a = a; this.b = b; } private int b; private int result; @Override public void run() { result = 0; try { for(int i=a;i<= b;i++) { result += i; Thread.sleep(100); } } catch (Exception e) { // TODO: handle exception } System.out.printf('(%s) - 運(yùn)行結(jié)束,結(jié)果為 %dn',Thread.currentThread().getName(),result); } public int getResult() {//獲取線程返回結(jié)果 return result; } }}
第二種方法:使用 Callable 和 FutureTask。
使用 FutureTask 的過程如下:(1)通過一個(gè) Callable 任務(wù)或者一個(gè) Runnable(一開始就指定 result)任務(wù)構(gòu)造 FutureTask;(2)將 FutureTask 交給 Thread 去運(yùn)行;(3)使用 FutureTask 的 get 方法(或者 Thread 的 join 方法)阻塞當(dāng)前線程直到獲得任務(wù)的結(jié)果。
import java.util.*;import java.util.concurrent.*;public class CallableTest { public static void main(String[] args) throws Exception { System.out.println('使用 Callable 獲得返回結(jié)果:');List<FutureTask<Integer>> futureTasks = new ArrayList<>(10); // 新建 10 個(gè)線程,每個(gè)線程分別負(fù)責(zé)累加 1~10, 11~20, ..., 91~100 for (int i = 0; i < 10; i++) { AccumCallable task = new AccumCallable(i * 10 + 1, (i + 1) * 10); FutureTask<Integer> futureTask = new FutureTask<>(task); futureTasks.add(futureTask); Thread worker = new Thread(futureTask, '慢速累加器線程' + i); worker.start(); } int total = 0; for (FutureTask<Integer> futureTask : futureTasks) { total += futureTask.get(); // get() 方法會(huì)阻塞直到獲得結(jié)果 } System.out.println('累加的結(jié)果: ' + total); } static final class AccumCallable implements Callable<Integer> { private final int begin; private final int end; public AccumCallable(int begin, int end) { this.begin = begin; this.end = end; } @Override public Integer call() throws Exception { int result = 0; for (int i = begin; i <= end; i++) {result += i;Thread.sleep(100); } System.out.printf('(%s) - 運(yùn)行結(jié)束,結(jié)果為 %dn', Thread.currentThread().getName(), result); return result; } } }
二:FutureTask介紹
FutureTask可用于異步獲取執(zhí)行結(jié)果或取消執(zhí)行任務(wù)的場(chǎng)景。通過傳入Runnable或者Callable的任務(wù)給FutureTask,直接調(diào)用其run方法或者放入線程池執(zhí)行,之后可以在外部通過FutureTask的get方法異步獲取執(zhí)行結(jié)果。因此,**FutureTask非常適合用于耗時(shí)的計(jì)算,主線程可以在完成自己的任務(wù)后,再去獲取結(jié)果。**另外,F(xiàn)utureTask還可以確保即使調(diào)用了多次run方法,它都只會(huì)執(zhí)行一次Runnable或者Callable任務(wù),或者通過cancel取消FutureTask的執(zhí)行等。
一個(gè)FutureTask 可以用來包裝一個(gè) Callable 或是一個(gè)runnable對(duì)象。因?yàn)镕urtureTask實(shí)現(xiàn)了Runnable方法,所以一個(gè) FutureTask可以提交(submit)給一個(gè)Excutor執(zhí)行(excution)。
FutureTask執(zhí)行多任務(wù)計(jì)算的使用場(chǎng)景:
利用FutureTask和ExecutorService,可以用多線程的方式提交計(jì)算任務(wù),主線程繼續(xù)執(zhí)行其他任務(wù),當(dāng)主線程需要子線程的計(jì)算結(jié)果時(shí),再異步獲取子線程的執(zhí)行結(jié)果。
import java.util.*;import java.util.concurrent.*;public class FutureTest1 { public static void main(String[] args) { Task task = new Task();// 新建異步任務(wù),然后執(zhí)行futureTask FutureTask<Integer> future = new FutureTask<Integer>(task) { // 異步任務(wù)執(zhí)行完成,回調(diào) @Override protected void done() {try { System.out.println('future.done():' + get());} catch (InterruptedException e) { e.printStackTrace();} catch (ExecutionException e) { e.printStackTrace();} } }; // 創(chuàng)建線程池(使用了預(yù)定義的配置) ExecutorService executor = Executors.newCachedThreadPool(); executor.execute(future); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } // 可以取消異步任務(wù) // future.cancel(true); try { // 阻塞,等待異步任務(wù)執(zhí)行完畢-獲取異步任務(wù)的返回值 System.out.println('future.get():' + future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } // 異步任務(wù) static class Task implements Callable<Integer> { // 返回異步任務(wù)的執(zhí)行結(jié)果 @Override public Integer call() throws Exception { int i = 0; for (; i < 10; i++) {try { System.out.println('異步任務(wù):'+Thread.currentThread().getName() + '_' + i); Thread.sleep(500);} catch (InterruptedException e) { e.printStackTrace();} } return i; } }}
參考文章:https://blog.csdn.net/chenliguan/article/details/54345993https://blog.csdn.net/linchunquan/article/details/22382487https://segmentfault.com/a/1190000007767231
到此這篇關(guān)于淺談Java獲得多線程的返回結(jié)果方式的文章就介紹到這了,更多相關(guān)Java 多線程的返回結(jié)果內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. CentOS郵件服務(wù)器搭建系列—— POP / IMAP 服務(wù)器的構(gòu)建( Dovecot )2. HTTP協(xié)議常用的請(qǐng)求頭和響應(yīng)頭響應(yīng)詳解說明(學(xué)習(xí))3. ASP.NET MVC通過勾選checkbox更改select的內(nèi)容4. IntelliJ IDEA創(chuàng)建web項(xiàng)目的方法5. Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié)6. 存儲(chǔ)于xml中需要的HTML轉(zhuǎn)義代碼7. .NET 6實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例詳解8. django創(chuàng)建css文件夾的具體方法9. ASP中實(shí)現(xiàn)字符部位類似.NET里String對(duì)象的PadLeft和PadRight函數(shù)10. 原生JS實(shí)現(xiàn)記憶翻牌游戲
