小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Callable的Future模式

 印度阿三17 2020-03-23

Callable

  在java中,創(chuàng)建線程一般有兩種方式,一種是繼承Thread類,一種是實(shí)現(xiàn)Runnable接口。然而,這兩種方式的缺點(diǎn)是在線程任務(wù)執(zhí)行結(jié)束后,無法獲取執(zhí)行結(jié)果。我們一般只能采用共享變量或共享存儲(chǔ)以及線程通信的方式實(shí)現(xiàn)獲得任務(wù)結(jié)果的目的;  

  不過,在java中,也提供了使用Callable和Future來實(shí)現(xiàn)獲取任務(wù)結(jié)果的操作。Callable用來執(zhí)行任務(wù),產(chǎn)生結(jié)果,而Future用來獲得結(jié)果;

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

  Callable和Runnable的區(qū)別:

    1.Callable能接受一個(gè)泛型,然后在call方法中返回一個(gè)這個(gè)類型的值,而Runnable的run方法沒有返回值;

    2.Callable的call方法可以拋出異常,而Runnable的run方法不會(huì)拋出異常;

Future模式

  Future莫斯的核心在于:去除了函數(shù)的等待時(shí)間,并使得原來需要等待的時(shí)間段可以用于處理其他業(yè)務(wù)邏輯;

  Future模式:對(duì)于多線程,如果線程A要等待線程B的結(jié)果,那么線程A沒有必要等待線程B,知道線程B有結(jié)果,可以先拿到一個(gè)未來的Future,等線程B有結(jié)果時(shí)再取真實(shí)的結(jié)果; 

package com.wn.callable;

import java.util.concurrent.*;

public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("callable接口中重寫的call方法,可以有返回值并且拋出異常?。?!");
        return "callable";
    }

    //方案一
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        //利用FutureTask執(zhí)行callable并且接受結(jié)構(gòu)
        FutureTask<String> stringFutureTask = new FutureTask<String>(myCallable);
        //利用線程執(zhí)行task任務(wù)
        new Thread(stringFutureTask).start();
        //接受結(jié)果,get方法會(huì)發(fā)生阻塞情況
        System.out.println(stringFutureTask.get());
        System.out.println("mycallable執(zhí)行完畢!");
    }

}
package com.wn.callable;

import java.util.concurrent.*;

public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("callable接口中重寫的call方法,可以有返回值并且拋出異常?。。?);
        return "callable";
    }

    //方案二:submit(Callable task)
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        //創(chuàng)建一個(gè)線程
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        //創(chuàng)建線程執(zhí)行任務(wù),接受任務(wù)結(jié)果
        Future submit = executorService.submit(myCallable);
        //接受返回值,get方法會(huì)阻塞當(dāng)前線程
        System.out.println(submit.get());
        System.out.println("利用線程池執(zhí)行mycallable,完畢!?。?);
        //停止
        executorService.shutdown();
    }
}

Future常用方法

  V get():獲取異步執(zhí)行的結(jié)果,如果沒有結(jié)果可用,此方法會(huì)阻塞知道異步計(jì)算完成;

  V get(Long timeout,TimeUnit unit):獲取異步執(zhí)行結(jié)果,如果沒喲結(jié)果可用,此方法會(huì)阻塞,但是會(huì)有時(shí)間限制,如果阻塞時(shí)間超過設(shè)定的timeout時(shí)間,該方法將拋出異常;

  boolean isDone():如果任務(wù)執(zhí)行結(jié)束,無論是正常結(jié)束或是中途取消還是發(fā)生異常,都返回true;

  boolean isCanceller():如果任務(wù)完成前被取消,則返回true;

  boolean cancel(boolean mayInterrupRunning):如果任務(wù)還沒有開始,執(zhí)行cancel方法將返回false;如果任務(wù)已經(jīng)啟動(dòng),執(zhí)行cancel方法將以中斷執(zhí)行此任務(wù)線程的方式來試圖停止任務(wù),如果停止成功,返回true;

  當(dāng)任務(wù)已經(jīng)啟動(dòng),執(zhí)行cancel(false)方法將不會(huì)對(duì)正在執(zhí)行的任務(wù)線程產(chǎn)生影響(讓線程正常執(zhí)行到完成),此時(shí)返回false;

  當(dāng)任務(wù)已經(jīng)啟動(dòng),執(zhí)行cancel方法將返回false,MayInterruptRunning參數(shù)表示是否中斷執(zhí)行中的線程;

  實(shí)際上Future提供了三種功能:

    1.能夠中斷執(zhí)行中的任務(wù);

    2.判斷任務(wù)是否執(zhí)行完成;

    3.獲取任務(wù)執(zhí)行完成后的結(jié)果;

get()方法的阻塞性

package com.wn.callable;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

public class FutureGet {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor=Executors.newFixedThreadPool(2);
        //創(chuàng)建一個(gè)Callable,三秒返回String類型
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(3000);
                System.out.println("callable方法執(zhí)行!");
                return "callable";
            }
        };
        System.out.println("提交任務(wù)之前:" getStringDate());
        Future future = executor.submit(callable);
        System.out.println("提供任務(wù)之后,獲取結(jié)果之前:" getStringDate());
        System.out.println("獲取返回值:" future.get());
        System.out.println("獲取到結(jié)果之后:" getStringDate());
    }

    public static String getStringDate(){
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        String dataString = format.format(date);
        return dataString;
    }
}

    

  通過上面的輸出可以看到,在調(diào)動(dòng)submit提交任務(wù)之后,主線程本來是繼續(xù)運(yùn)行到future.get()的時(shí)候就阻塞了,一直等到任務(wù)執(zhí)行完畢,拿到了返回的返回值,主線程才會(huì)繼續(xù)運(yùn)行;

  阻塞性是因?yàn)檎{(diào)用了get()方法時(shí),任務(wù)沒有執(zhí)行完畢,所以會(huì)一直等到任務(wù)完成,形成了阻塞;

  任務(wù)是在調(diào)用submit方法時(shí)就開始執(zhí)行了,如果在調(diào)用get方法時(shí),任務(wù)已經(jīng)執(zhí)行完畢,那么就不會(huì)造成阻塞;

  下面調(diào)用方法前先休眠四秒,這時(shí)能馬上得到返回值:

        System.out.println("提交任務(wù)之前:" getStringDate());
        Future future = executor.submit(callable);
        System.out.println("提供任務(wù)之后,獲取結(jié)果之前:" getStringDate());
        Thread.sleep(4000);
        System.out.println("休眠四秒:" getStringDate());
        System.out.println("獲取返回值:" future.get());
        System.out.println("獲取到結(jié)果之后:" getStringDate());

    

  可以看到,因?yàn)樾菝吡怂拿?,任?wù)已經(jīng)執(zhí)行完畢,所以get方法立馬就得到了結(jié)果;

submit(Runnable task)

  因?yàn)镽unnable是沒有返回值,所以如果submit一個(gè)Runnable的話,get得到的值肯定為null;

public class SubmitRunnable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor= Executors.newFixedThreadPool(2);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Future future = executor.submit(runnable);
        System.out.println("獲得返回值:" future.get());
    }
}

    

submit(Runnable task,T result)

  雖然傳入Runnable不能直接返回內(nèi)容,但是可以通過submit(Runnable task,T result)傳入一個(gè)載體,通過這個(gè)載體獲取返回值;

  創(chuàng)建一個(gè)類Data:

package com.wn.callable;

public class Data {
    String name;
    String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

  在Runnable的構(gòu)造方法中傳入:

package com.wn.callable;

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

public class MyThreadData implements Runnable {
    Data data;

    public MyThreadData(Data data) {
        this.data = data;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("線程執(zhí)行:");
            data.setName("張三");
            data.setSex("女");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] arg) throws ExecutionException, InterruptedException {
        ExecutorService executor= Executors.newFixedThreadPool(2);
        Data data = new Data();
        Future<Data> submit = executor.submit(new MyThreadData(data), data);
        System.out.println("返回結(jié)果:" submit.get().getName() ",sex:" submit.get().getSex());
    }
}

    

get(long var1,TimeUnit var3)

  前面用的get方法獲取返回值,因?yàn)榉椒ㄗ枞袝r(shí)需要等很久的時(shí)間,所以可以設(shè)置超時(shí)時(shí)間;

package com.wn.callable;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

public class GetTime {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ExecutorService executor= Executors.newFixedThreadPool(2);
        //創(chuàng)建一個(gè)Callable,三秒返回String類型
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(3000);
                System.out.println("callable方法執(zhí)行!");
                return "callable";
            }
        };
        System.out.println("提交任務(wù)之前:" getStringDate());
        Future future = executor.submit(callable);
        System.out.println("提供任務(wù)之后,獲取結(jié)果之前:" getStringDate());
        System.out.println("獲取返回值:" future.get(2,TimeUnit.SECONDS));
        System.out.println("獲取到結(jié)果之后:" getStringDate());
    }

    public static String getStringDate(){
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        String dataString = format.format(date);
        return dataString;
    }
}

    

?  如果在二秒內(nèi)沒有獲取,就拋出異常,主線程繼續(xù)運(yùn)行,不會(huì)在繼續(xù)阻塞;

?

來源:https://www./content-4-665401.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多