国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【Java并發(fā)】Runnable、Callable、Future、FutureTask

zhaot / 1506人閱讀

摘要:聲明了幾種方法,其中有一個(gè)就是傳入聲明了對(duì)具體的或者任務(wù)執(zhí)行進(jìn)行取消查詢結(jié)果獲取等方法。事實(shí)上,是接口的一個(gè)唯一實(shí)現(xiàn)類。使用示例第一種方式是使用繼承了的線程池中的方法,將直接提交創(chuàng)建。

創(chuàng)建線程的兩種方式

直接繼承 Thread

實(shí)現(xiàn) Runnable 接口

這兩種方式都有一個(gè)缺點(diǎn):在執(zhí)行完成任務(wù)之后,無法直接獲取到最后的執(zhí)行結(jié)果。如果需要獲取執(zhí)行結(jié)果,就必須通過共享變量線程通信的方式來達(dá)到想要的效果,較為麻煩。

所以從 Java 1.5 起,就提供了兩種方式:CallableFuture,通過它們可以在任務(wù)執(zhí)行結(jié)束后得到任務(wù)執(zhí)行結(jié)果。

Runnable 與 Callable

首先是 java.lang.Rannable,它是一個(gè)接口,里面只聲明了一個(gè) run() 方法:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

由于 run() 方法的返回值類型為 void,所以在線程執(zhí)行完后無任何返回結(jié)果。

然后是 java.util.concurrent.Callable,它也是一個(gè)接口,也只聲明了一個(gè)方法,其名為 call()

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

可以看到,這是一個(gè)泛型接口,返回的類型就是傳進(jìn)來的 V 類型。

那么,如何使用 Callable 呢?一般是結(jié)合 ExecutorService 來使用。ExecutorService 聲明了幾種 submit 方法,其中有一個(gè)就是傳入 Callable

 Future submit(Callable task);
Future

Future 聲明了對(duì)具體的 Runnable 或者 Callable 任務(wù)執(zhí)行進(jìn)行取消、查詢、結(jié)果獲取等方法。必要時(shí)可以通過 get 方法獲取執(zhí)行結(jié)果,該方法會(huì)阻塞直到任務(wù)返回結(jié)果。

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

由此可見,Future 提供了三種功能:

取消任務(wù):參數(shù)表示是否允許中途取消(中斷)

判斷狀態(tài):是否已取消、是否已完成

獲取結(jié)果:兩種方式,指不指定時(shí)間

因?yàn)?Future 只是一個(gè)接口,所以無法直接用來創(chuàng)建對(duì)象,因此有了下面的 FutureTask

FutureTask

首先看下 FutureTask 的繼承關(guān)系:

可以看出 RunnableFuture 繼承了 Runnable 接口和 Future 接口,而 FutureTask 實(shí)現(xiàn)了 RunnableFuture 接口。所以它既可以作為 Runnable 被線程執(zhí)行,又可以作為 Future 得到 Callable 的返回值

然后可以看到 FutureTask 內(nèi)部有這幾種狀態(tài):

private volatile int state;
private static final int NEW          = 0;
private static final int COMPLETING   = 1;
private static final int NORMAL       = 2;
private static final int EXCEPTIONAL  = 3;
private static final int CANCELLED    = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED  = 6;

再根據(jù)注釋,可以得知當(dāng)創(chuàng)建一個(gè) FutureTask 對(duì)象時(shí),初始狀態(tài)是 NEW,在運(yùn)行過程中,運(yùn)行狀態(tài)僅在方法setsetExceptioncancel 中轉(zhuǎn)換為終端狀態(tài)。有四種狀態(tài)轉(zhuǎn)換過程:

NEW -> COMPLETING -> NORMAL:正常執(zhí)行并返回結(jié)果(run 執(zhí)行成功再設(shè)置狀態(tài)為 COMPLETING

NEW -> COMPLETING -> EXCEPTIONAL:執(zhí)行過程中出現(xiàn)異常(setException 先設(shè)置狀態(tài)為 COMPLETING

NEW -> CANCELLED:執(zhí)行前被取消

NEW -> INTERRUPTING -> INTERRUPTED:執(zhí)行時(shí)被中斷(cancel 參數(shù)為 true 才可能出現(xiàn)這個(gè)狀態(tài))

最后來看下 FutureTask 的兩個(gè)構(gòu)造器:

public FutureTask(Callable callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

可知傳入的任務(wù)最后都是付給內(nèi)部的 private Callable callable

事實(shí)上,FutureTaskFuture 接口的一個(gè)唯一實(shí)現(xiàn)類。

更多關(guān)于 FutureTask 的源碼分析,可以看 FutureTask源碼解析 這篇文章。
使用示例 Future

第一種方式是使用繼承了 ExecutorService 的線程池 ThreadPoolExecutor 中的 submit 方法,將 Callable 直接提交創(chuàng)建 Future

import java.util.concurrent.*;
public class FutureExample {
    static class MyCallable implements Callable {
        @Override
        public String call() throws Exception {
            System.out.println("do something in callable");
            Thread.sleep(5000);
            return "Ok";
        }
    }
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future future = executorService.submit(new MyCallable());
        System.out.println("do something in main");
        Thread.sleep(1000);
        String result = future.get();
        System.out.println("result: " + result);
    }
}
FutureTask

第二種方法是創(chuàng)建一個(gè)寫好 CallableFutureTask 對(duì)象實(shí)例,再 submit。因?yàn)?FutureTask 內(nèi)部本身?yè)碛?run 方法,也可以直接創(chuàng)建線程 Thread 運(yùn)行。

利用 ExecutorService

import java.util.concurrent.*
public class FutureTaskWithExecutorService {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        FutureTask futureTask = new FutureTask<>(() -> { // java 8 函數(shù)式寫法
            System.out.println("do something in callable");
            Thread.sleep(5000);
            return "Ok";
        });
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(futureTask);
        System.out.println("do something in main");
        Thread.sleep(1000);
        String result = futureTask.get();
        System.out.println("result: " + result);
    }
}

利用 Thread

import java.util.concurrent.*
public class FutureTaskWithThread {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        FutureTask futureTask = new FutureTask<>(new Callable() {
            @Override
            public String call() throws Exception {
                System.out.println("do something in callable");
                Thread.sleep(5000);
                return "Ok";
            }
        });
        new Thread(futureTask).start();
        System.out.println("do something in main");
        Thread.sleep(1000);
        String result = futureTask.get();
        System.out.println("result: " + result);
    }
}
參考資料

Java并發(fā)編程:Callable、Future和FutureTask

FutureTask源碼解析

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76857.html

相關(guān)文章

  • 初讀《Java并發(fā)編程的藝術(shù)》-第十章:Executor框架 -10.1 Executor框架簡(jiǎn)介

    摘要:線程的啟動(dòng)與銷毀都與本地線程同步。操作系統(tǒng)會(huì)調(diào)度所有線程并將它們分配給可用的。框架的成員主要成員線程池接口接口接口以及工具類。創(chuàng)建單個(gè)線程的接口與其實(shí)現(xiàn)類用于表示異步計(jì)算的結(jié)果。參考書籍并發(fā)編程的藝術(shù)方騰飛魏鵬程曉明著 在java中,直接使用線程來異步的執(zhí)行任務(wù),線程的每次創(chuàng)建與銷毀需要一定的計(jì)算機(jī)資源開銷。每個(gè)任務(wù)創(chuàng)建一個(gè)線程的話,當(dāng)任務(wù)數(shù)量多的時(shí)候,則對(duì)應(yīng)的創(chuàng)建銷毀開銷會(huì)消耗大量...

    aisuhua 評(píng)論0 收藏0
  • Java并發(fā)編程之多線程和線程池

    摘要:目標(biāo)線程由運(yùn)行狀態(tài)轉(zhuǎn)換為就緒狀態(tài),也就是讓出執(zhí)行權(quán)限,讓其他線程得以優(yōu)先執(zhí)行,但其他線程能否優(yōu)先執(zhí)行時(shí)未知的。函數(shù)的官方解釋是意思是使調(diào)用該函數(shù)的線程讓出執(zhí)行時(shí)間給其他已就緒狀態(tài)的線程。 線程允許在同一個(gè)進(jìn)程中同時(shí)存在多個(gè)程序控制流,即通過線程可以實(shí)現(xiàn)同時(shí)處理多個(gè)任務(wù)的功能。線程會(huì)共享進(jìn)程范圍內(nèi)的資源,例如內(nèi)存句柄和文件句柄,但每個(gè)線程都有各自的程序計(jì)數(shù)器、棧以及局部變量。 多線程的實(shí)...

    wums 評(píng)論0 收藏0
  • java并發(fā)編程學(xué)習(xí)2--Future

    摘要:一個(gè)線程池包含很多準(zhǔn)備運(yùn)行的空閑線程,每當(dāng)執(zhí)行完畢后,線程不會(huì)死亡而是回到線程池準(zhǔn)備為下一個(gè)請(qǐng)求提供服務(wù)。另一個(gè)使用線程池的理由是減少并發(fā)線程數(shù)。創(chuàng)建大量線程會(huì)大大降低性能甚至拖垮虛擬機(jī)。 【Future的概念 interface Future ,表示異步計(jì)算的結(jié)果,F(xiàn)uture有個(gè)get方法而獲取結(jié)果只有在計(jì)算完成時(shí)獲取,否則會(huì)一直阻塞直到任務(wù)轉(zhuǎn)入完成狀態(tài),然后會(huì)返回結(jié)果或者拋出異常...

    weizx 評(píng)論0 收藏0
  • Java多線程學(xué)習(xí)(八)線程池與Executor 框架

    摘要:一使用線程池的好處線程池提供了一種限制和管理資源包括執(zhí)行一個(gè)任務(wù)。每個(gè)線程池還維護(hù)一些基本統(tǒng)計(jì)信息,例如已完成任務(wù)的數(shù)量。通過重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗。使用無界隊(duì)列作為線程池的工作隊(duì)列會(huì)對(duì)線程池帶來的影響與相同。 歷史優(yōu)質(zhì)文章推薦: Java并發(fā)編程指南專欄 分布式系統(tǒng)的經(jīng)典基礎(chǔ)理論 可能是最漂亮的Spring事務(wù)管理詳解 面試中關(guān)于Java虛擬機(jī)(jvm)的問...

    cheng10 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

zhaot

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<