java線程學習記錄(二)

Callable,Future與FutureTask

做用

經過實現Callable接口一樣可以建立一個線程,但與Runnable接口不一樣的是Callable接口有返回值。java

Callable接口

JDK源碼併發

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

能夠看出,與Runnable一樣屬於一個接口方法,但二者不一樣的是,Callable接口有返回值且支持泛型。ide

使用

Callable的使用通常是配置線程池ExecutorService來使用。其能夠經過一個submit()方法來讓一個Callable接口執行,返回一個Future。經過Future的get方法能夠得到結果。
案例工具

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Demo03 {
    
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 建立一個線程池
        ExecutorService es=Executors.newCachedThreadPool();
        // 建立線程對象
        MyThread mt=new MyThread();
        //使用Future
        Future<Integer> fu=es.submit(mt);
        //經過get方法得到返回值
        System.out.println(fu.get());
        
    }

}
class MyThread implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        // TODO Auto-generated method stub
        Thread.sleep(1000);
        return 2;
    }
    
}

get方法調用後會阻塞當前線程,實際使用時建議重寫get方法,使用能夠設置超時時間的重載get方法。線程

Future接口

JDK源碼code

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

其中cancel方法是試圖取消一個線程的執行。
cancel並不必定能取消線程的執行,由於一個任務可能已完成,已取消或者一些其它緣由,存在取消失敗的可能。
返回值boolean,當取消成功返回true,失敗返回false。
參數mayInterruptIfRunning,表示是否使用中斷的方式取消線程執行。
因此有時候,爲了讓任務有可以取消的功能,就使⽤ Callable 來代替 Runnable 。
若是爲了可取消性⽽使⽤ Future 但⼜不提供可⽤的結果,則能夠聲明 Future<?> 形式類型、並返回 null 做爲底層任務的結果。對象

FutureTask類

JDK源碼繼承

public interface RunnableFuture<V> extends Runnable, Future<V>

FutureTask實現了RunnableFuture接口,而RunnableFuture接口則繼承了Runnable接口與Future接口。
FutureTask類至關因而一個工具類,使用它咱們不用本身去實現Future接口中那些複雜的抽象方法。
案例接口

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Demo04 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 建立線程池
        ExecutorService es=Executors.newCachedThreadPool();
        //建立FutureTask類
        FutureTask<Integer> ft=new FutureTask<>(new Task());
        //使用sumit方法
        es.submit(ft);
        //輸出
        System.out.println(ft.get());
    }

}
class Task implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        // TODO Auto-generated method stub
        Thread.sleep(1000);
        return 3;
    }
    
}

在不少⾼併發的環境下,有可能Callable和FutureTask會建立屢次。FutureTask可以在⾼併發環境下確保任務只執⾏⼀次。get

相關文章
相關標籤/搜索