1. 程式人生 > 程式設計 >淺談Java獲得多執行緒的返回結果方式(3種)

淺談Java獲得多執行緒的返回結果方式(3種)

一:Java建立執行緒方式

繼承Thread類或者實現Runnable介面。
但是Runnable 的 run() 方法是不帶返回值的,那如果我們需要一個耗時任務在執行完之後給予返回值,應該怎麼做呢?

第一種方法:在 Runnable 的實現類中設定一個變數 V,在 run 方法中將其改變為我們期待的結果,然後通過一個 getV() 方法將這個變數返回。

package com.test.thread;

import java.util.*;
import sun.swing.AccumulativeRunnable;
//獲得執行緒的返回結果方式一
/*
 *在runnable實現類中設定一個變數x,在run方法中將其改變為我們期待的結果,然後通過一個getX()方法將這個變數返回 
 */
public class RunnableTest {
 public static void main(String[] args) throws Exception {
  System.out.println("使用Runnable獲取返回結果");
  List<Thread> workers = new ArrayList<>(10);
  List<RunnableAcction> tasks = new ArrayList<>(10);
  //建立10個執行緒,每個執行緒分別負責累加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累加的結果:"+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) - 執行結束,結果為 %d\n",Thread.currentThread().getName(),result);
  }
    public int getResult() {//獲取執行緒返回結果
       return result;
    }
 }
}

第二種方法:使用 Callable 和 FutureTask。

使用 FutureTask 的過程如下:
(1)通過一個 Callable 任務或者一個 Runnable(一開始就指定 result)任務構造 FutureTask;
(2)將 FutureTask 交給 Thread 去執行;
(3)使用 FutureTask 的 get 方法(或者 Thread 的 join 方法)阻塞當前執行緒直到獲得任務的結果。

import java.util.*;
import java.util.concurrent.*;

public class CallableTest {

  public static void main(String[] args) throws Exception {
    System.out.println("使用 Callable 獲得返回結果:");
    
    List<FutureTask<Integer>> futureTasks = new ArrayList<>(10);
    // 新建 10 個執行緒,每個執行緒分別負責累加 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() 方法會阻塞直到獲得結果
    }
    System.out.println("累加的結果: " + 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) - 執行結束,結果為 %d\n",result);
      return result;
    }
  } 
}

二:FutureTask介紹

FutureTask可用於非同步獲取執行結果或取消執行任務的場景。通過傳入Runnable或者Callable的任務給FutureTask,直接呼叫其run方法或者放入執行緒池執行,之後可以在外部通過FutureTask的get方法非同步獲取執行結果。因此,**FutureTask非常適合用於耗時的計算,主執行緒可以在完成自己的任務後,再去獲取結果。**另外,FutureTask還可以確保即使呼叫了多次run方法,它都只會執行一次Runnable或者Callable任務,或者通過cancel取消FutureTask的執行等。

一個FutureTask 可以用來包裝一個 Callable 或是一個runnable物件。因為FurtureTask實現了Runnable方法,所以一個 FutureTask可以提交(submit)給一個Excutor執行(excution)。

FutureTask執行多工計算的使用場景:

利用FutureTask和ExecutorService,可以用多執行緒的方式提交計算任務,主執行緒繼續執行其他任務,當主執行緒需要子執行緒的計算結果時,再非同步獲取子執行緒的執行結果。

import java.util.*;
import java.util.concurrent.*;

public class FutureTest1 {

  public static void main(String[] args) {
  
    Task task = new Task();// 新建非同步任務,然後執行futureTask
    FutureTask<Integer> future = new FutureTask<Integer>(task) {
      // 非同步任務執行完成,回撥
      @Override
      protected void done() {
        try {
          System.out.println("future.done():" + get());
        } catch (InterruptedException e) {
          e.printStackTrace();
        } catch (ExecutionException e) {
          e.printStackTrace();
        }
      }
    };
    // 建立執行緒池(使用了預定義的配置)
    ExecutorService executor = Executors.newCachedThreadPool();
    executor.execute(future);

    try {
      Thread.sleep(1000);
    } catch (InterruptedException e1) {
      e1.printStackTrace();
    }
    // 可以取消非同步任務
    // future.cancel(true);

    try {
      // 阻塞,等待非同步任務執行完畢-獲取非同步任務的返回值
      System.out.println("future.get():" + future.get());
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
  }

  // 非同步任務
  static class Task implements Callable<Integer> {
    // 返回非同步任務的執行結果
    @Override
    public Integer call() throws Exception {
      int i = 0;
      for (; i < 10; i++) {
        try {
          System.out.println("非同步任務:"+Thread.currentThread().getName() + "_"              + i);
          Thread.sleep(500);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      return i;
    }
  }
}

參考文章:
https://blog.csdn.net/chenliguan/article/details/54345993
https://blog.csdn.net/linchunquan/article/details/22382487
https://segmentfault.com/a/1190000007767231

到此這篇關於淺談Java獲得多執行緒的返回結果方式的文章就介紹到這了,更多相關Java 多執行緒的返回結果內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!