Future類的使用和原理

2021-10-10 02:13:23 字數 4435 閱讀 6050

future是concurrent包提供的一種非同步得到結果的介面。

future介面:

public

inte***ce

future

future裡面的任務,必須實現callable介面。

callable介面:

public

inte***ce

callable

state狀態當前計算的情況有下面這些狀態

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;

//對計算進行中斷

下面以futuretask類為例,敘述一遍future的使用方法和原理。

futuretask的實現介面:

測試**:

public

class

testmain};

futuretask

futuretask =

newfuturetask

(callable)

;new

thread

(futuretask)

.start()

; dishes dishes =

newdishes()

; dishes.

washdishes()

; clothes clothes = null;

trycatch

(interruptedexception e)

catch

(executionexception e)

if(clothes != null)

long end = system.

currenttimemillis()

; system.out.

println

("all tasks cost "

+(end - start)

+" millis");

/*執行結果:

start to wash dishes

machine starts to wash cloths

all dishes are cleaned!!!

all clothes are cleaned!!!

**********=over**********=

all tasks cost 3003 millis

*/}static

class

clothes

catch

(interruptedexception e)

system.out.

println

("all clothes are cleaned!!!");

}}static

class

dishes

catch

(interruptedexception e)

system.out.

println

("all dishes are cleaned!!!");}}}

由結果可看出future的方法是非同步的,所以總耗時是3s,如果同步的話應該是5s。

在**的最開頭,我們new了乙個callable物件,callable物件會被當做任務丟到futuretask裡面執行。

啟動執行緒就可以開始執行任務了。

下面具體說一下future幫我們幹了什麼,為什麼他是非同步的。

public

void

run(

)catch

(throwable ex)

if(ran)

set(result);}

}finally

}

run方法很直接,直接呼叫callable的call方法獲取值,獲取到值了,就令ran為true,然後呼叫set方法。

set方法會呼叫finishcompletion,

protected

void

set(v v)

}

waitnode節點是treiber stack的節點,就是乙個排隊等待的執行緒佇列。

private

void

finishcompletion()

waitnode next = q.next;

if(next == null)

break

; q.next = null;

// unlink to help gc

q = next;

}break;}

}done()

;// protected方法,鉤子函式,留給程式設計師自己實現

callable = null;

// to reduce footprint

}

public v get()

throws interruptedexception, executionexception

awaitdone用死迴圈等待結果,也就是說會阻塞在這裡。

private

intawaitdone

(boolean timed,

long nanos)

throws interruptedexception

int s = state;

if(s > completing)

// completing是乙個很短暫的狀態,呼叫thread.yield期望讓出時間片,之後重試迴圈

else

if(s == completing)

// cannot time out yet

thread.

yield()

;else

if(q == null)

q =newwaitnode()

;elseif(

!queued)

/* 當前節點未入棧

* 這是treiber stack演算法入棧的邏輯。

* treiber stack是乙個基於cas的無鎖併發棧實現,

*/queued = unsafe.

compareandswapobject

(this

, waitersoffset,

q.next = waiters, q)

;else

if(timed)

locksupport.

parknanos

(this

, nanos);}

else

//這裡阻塞住

locksupport.

park

(this);

}}

report把結果賦值回去

private v report

(int s)

throws executionexception

futuretask在底層開了乙個死迴圈用於等待結果,當執行緒得到結果時,跳出迴圈,藉此實現的非同步操作。注意,我們一般在使用future的時候,都不會用本文中new執行緒的方式,而是採用連線池中的執行緒。

使用Callable和Future介面建立執行緒

具體是建立callable介面的實現類,並實現clall 方法。並使用futuretask類來包裝callable實現類的物件,且以此futuretask物件作為thread物件的target來建立執行緒。看著好像有點複雜,直接來看乙個例子就清晰了。public class threadtest s...

Future和Callable的用法總結

executorservice service executors.newcachedthreadpool futurefu service.submit new callable system.out.println 傳送訊息 system.out.println 返回結果是 fu.get 200...

類和類的使用

class people name xiaoming 類屬性,類裡面的變數稱為屬性 age 18 私有屬性,別人知道後不會去動它,概念性問題 age 18 也是私有屬性,訪問會報錯 a people 例項化 print a.age 通過例項訪問類屬性,雖然是私有的,但是訪問還是可以列印,b peop...