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...