廖雪峯Java11多線程編程-3高級concurrent包-7Future

1. Runnable接口的限制

JDK提供了ExecutorService接口表示線程池,能夠經過submit提交一個任務。html

ExecutorService executor = Executors.newFixedThreadPool(4);
    executor.submit(task);

但這裏的task有個問題,由於繼承製Runnable,若是但願返回一個結果,只能用result來表示,這樣主線程獲取結果,就很不方便。java

class Task implements Runnable{
    public String result; //只能將結果保存到result,再去讀取
    public void run(){
        this.result = longTimeCalculation();
    }
}

所以JDK又提供了一個Callable<T>接口。app

2. Callable<T>接口

相比Runnable接口,Callable<T>接口多了一個返回值。這樣咱們就能夠用submit()方法把一個Callable的task提交給executor,異步執行。異步

<table border="1"><tr><td>不須要返回結果</td><td>須要返回結果</td></tr><tr><td>Runnable</td><td>Callable</td></tr></table> 當咱們使用Callable<T>接口時候,咱們須要實現一個泛型接口。例如咱們指望返回值是一個String,咱們就寫implements Callable<String>,並覆寫call()方法。 ```#java class Task implements Callable<String>{ public String call() throws Exception{ return longTimeCalculation(); } } ``` ## 3. Future <font color="red">若是得到異步執行的結果呢?</font> ```#java Callable<String> task = new Task(); ExecutorService executor = Executors.newFixedThreadPool(4); Future<String> future = exector.submit(task); String result = future.get(); //可能阻塞 ``` <font color="blue">當咱們提交一個Callable任務之後,會同時得到一個Future對象。 接着在主線程的某個時刻調用Future對象的get()方法就能夠得到異步執行的結果: * 在調用get()方法的時候,若是異步任務已經完成,就直接得到結果; * 若是異步任務未完成,那麼get()方法就會阻塞,直到任務完成之後,返回結果。 </font>ui

Future<V>接口:表示一個將來可能會返回的結果this

get():返回一個異步執行的結果
    get(long timeout, TimeUnit unit):指定一個最長的等待時間
    cancel(boolean mayInterruptIfRunning):中斷一個異步任務的執行
    isDone():判斷當前的異步任務是否已經完成

4. 示例

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class DownloadTask implements Callable<String> {
    String url;
    public DownloadTask(String url){
        this.url = url;
    }
    public String call() throws Exception {
        System.out.println("start download " + url + "...");
        URLConnection conn = new URL(this.url).openConnection();
        conn.connect();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))){

            String s = null;
            StringBuilder sb = new StringBuilder();
            while ((s = reader.readLine()) != null) {
                sb.append(s).append("\n");
            }
            return sb.toString();
        }

    }

}
public class Main{
    public static void main(String[] args) throws Exception{
        ExecutorService executor = Executors.newFixedThreadPool(3);
        DownloadTask task = new DownloadTask("https://www.sina.com.cn");
        Future<String> future = executor.submit(task);
        String html = future.get();
        System.out.println(html);
        executor.shutdown();
    }
}

5.總結:

  • 須要返回結果,使用Callable;不須要返回結果,使用Runnable
  • 提交Callable任務,能夠得到一個Future對象
  • 能夠用Future在未來某個時刻得到結果
相關文章
相關標籤/搜索