Java中的Runnable、Callable、Future、FutureTask的區別與示例

原文地址:http://blog.csdn.net/bboyfeiyu/article/details/24851847

---------------------------------------------------------

Java中存在Runnable、Callable、Future、FutureTask這幾個與線程相關的類或者接口,在Java中也是比較重要的幾個概念,我們通過下面的簡單示例來了解一下它們的作用于區別。

Runnable

其中Runnable應該是我們最熟悉的接口,它只有一個run()函數,用于將耗時操作寫在其中,該函數沒有返回值。然后使用某個線程去執行該runnable即可實現多線程,Thread類在調用start()函數后就是執行的是Runnable的run()函數。Runnable的聲明如下 :?

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. public?interface?Runnable?{??
  2. ????/**?
  3. ?????*?When?an?object?implementing?interface?<code>Runnable</code>?is?used?
  4. ?????*?to?create?a?thread,?starting?the?thread?causes?the?object's?
  5. ?????*?<code>run</code>?method?to?be?called?in?that?separately?executing?
  6. ?????*?thread.?
  7. ?????*?<p>?
  8. ?????*?
  9. ?????*?@see?????java.lang.Thread#run()?
  10. ?????*/??
  11. ????public?abstract?void?run();??
  12. }??

Callable

Callable與Runnable的功能大致相似,Callable中有一個call()函數,但是call()函數有返回值,而Runnable的run()函數不能將結果返回給客戶程序。Callable的聲明如下 :

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. public?interface?Callable<V>?{??
  2. ????/**?
  3. ?????*?Computes?a?result,?or?throws?an?exception?if?unable?to?do?so.?
  4. ?????*?
  5. ?????*?@return?computed?result?
  6. ?????*?@throws?Exception?if?unable?to?compute?a?result?
  7. ?????*/??
  8. ????V?call()?throws?Exception;??
  9. }??
可以看到,這是一個泛型接口,call()函數返回的類型就是客戶程序傳遞進來的V類型。

Future

Executor就是Runnable和Callable的調度容器,Future就是對于具體的Runnable或者Callable任務的執行結果進行

取消、查詢是否完成、獲取結果、設置結果操作。get方法會阻塞,直到任務返回結果(Future簡介)。Future聲明如下 :

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. *?@see?FutureTask?
  3. ?*?@see?Executor?
  4. ?*?@since?1.5?
  5. ?*?@author?Doug?Lea?
  6. ?*?@param?<V>?The?result?type?returned?by?this?Future's?<tt>get</tt>?method?
  7. ?*/??
  8. public?interface?Future<V>?{??
  9. ??
  10. ????/**?
  11. ?????*?Attempts?to?cancel?execution?of?this?task.??This?attempt?will?
  12. ?????*?fail?if?the?task?has?already?completed,?has?already?been?cancelled,?
  13. ?????*?or?could?not?be?cancelled?for?some?other?reason.?If?successful,?
  14. ?????*?and?this?task?has?not?started?when?<tt>cancel</tt>?is?called,?
  15. ?????*?this?task?should?never?run.??If?the?task?has?already?started,?
  16. ?????*?then?the?<tt>mayInterruptIfRunning</tt>?parameter?determines?
  17. ?????*?whether?the?thread?executing?this?task?should?be?interrupted?in?
  18. ?????*?an?attempt?to?stop?the?task.?????*?
  19. ?????*/??
  20. ????boolean?cancel(boolean?mayInterruptIfRunning);??
  21. ??
  22. ????/**?
  23. ?????*?Returns?<tt>true</tt>?if?this?task?was?cancelled?before?it?completed?
  24. ?????*?normally.?
  25. ?????*/??
  26. ????boolean?isCancelled();??
  27. ??
  28. ????/**?
  29. ?????*?Returns?<tt>true</tt>?if?this?task?completed.?
  30. ?????*?
  31. ?????*/??
  32. ????boolean?isDone();??
  33. ??
  34. ????/**?
  35. ?????*?Waits?if?necessary?for?the?computation?to?complete,?and?then?
  36. ?????*?retrieves?its?result.?
  37. ?????*?
  38. ?????*?@return?the?computed?result?
  39. ?????*/??
  40. ????V?get()?throws?InterruptedException,?ExecutionException;??
  41. ??
  42. ????/**?
  43. ?????*?Waits?if?necessary?for?at?most?the?given?time?for?the?computation?
  44. ?????*?to?complete,?and?then?retrieves?its?result,?if?available.?
  45. ?????*?
  46. ?????*?@param?timeout?the?maximum?time?to?wait?
  47. ?????*?@param?unit?the?time?unit?of?the?timeout?argument?
  48. ?????*?@return?the?computed?result?
  49. ?????*/??
  50. ????V?get(long?timeout,?TimeUnit?unit)??
  51. ????????throws?InterruptedException,?ExecutionException,?TimeoutException;??
  52. }??

FutureTask

FutureTask則是一個RunnableFuture<V>,而RunnableFuture實現了Runnbale又實現了Futrue<V>這兩個接口,

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. public?class?FutureTask<V>?implements?RunnableFuture<V>??
RunnableFuture

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. public?interface?RunnableFuture<V>?extends?Runnable,?Future<V>?{??
  2. ????/**?
  3. ?????*?Sets?this?Future?to?the?result?of?its?computation?
  4. ?????*?unless?it?has?been?cancelled.?
  5. ?????*/??
  6. ????void?run();??
  7. }??

另外它還可以包裝Runnable和Callable<V>, 由構造函數注入依賴。

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. public?FutureTask(Callable<V>?callable)?{??
  2. ????if?(callable?==?null)??
  3. ????????throw?new?NullPointerException();??
  4. ????this.callable?=?callable;??
  5. ????this.state?=?NEW;???????//?ensure?visibility?of?callable??
  6. }??
  7. ??
  8. public?FutureTask(Runnable?runnable,?V?result)?{??
  9. ????this.callable?=?Executors.callable(runnable,?result);??
  10. ????this.state?=?NEW;???????//?ensure?visibility?of?callable??
  11. }??
可以看到,Runnable注入會被Executors.callable()函數轉換為Callable類型,即FutureTask最終都是執行Callable類型的任務。該適配函數的實現如下 :

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. public?static?<T>?Callable<T>?callable(Runnable?task,?T?result)?{??
  2. ????if?(task?==?null)??
  3. ????????throw?new?NullPointerException();??
  4. ????return?new?RunnableAdapter<T>(task,?result);??
  5. }??
RunnableAdapter適配器

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. /**?
  2. ?*?A?callable?that?runs?given?task?and?returns?given?result?
  3. ?*/??
  4. static?final?class?RunnableAdapter<T>?implements?Callable<T>?{??
  5. ????final?Runnable?task;??
  6. ????final?T?result;??
  7. ????RunnableAdapter(Runnable?task,?T?result)?{??
  8. ????????this.task?=?task;??
  9. ????????this.result?=?result;??
  10. ????}??
  11. ????public?T?call()?{??
  12. ????????task.run();??
  13. ????????return?result;??
  14. ????}??
  15. }??

由于FutureTask實現了Runnable,因此它既可以通過Thread包裝來直接執行,也可以提交給ExecuteService來執行。

并且還可以直接通過get()函數獲取執行結果,該函數會阻塞,直到結果返回。因此FutureTask既是Future、

Runnable,又是包裝了Callable( 如果是Runnable最終也會被轉換為Callable ), 它是這兩者的合體。


簡單示例

[java]?view plaincopy
在CODE上查看代碼片派生到我的代碼片
  1. ?package?com.effective.java.concurrent.task;??
  2. ??
  3. import?java.util.concurrent.Callable;??
  4. import?java.util.concurrent.ExecutionException;??
  5. import?java.util.concurrent.ExecutorService;??
  6. import?java.util.concurrent.Executors;??
  7. import?java.util.concurrent.Future;??
  8. import?java.util.concurrent.FutureTask;??
  9. ??
  10. /**?
  11. ?*??
  12. ?*?@author?mrsimple?
  13. ?*?
  14. ?*/??
  15. public?class?RunnableFutureTask?{??
  16. ??
  17. ????/**?
  18. ?????*?ExecutorService?
  19. ?????*/??
  20. ????static?ExecutorService?mExecutor?=?Executors.newSingleThreadExecutor();??
  21. ??
  22. ????/**?
  23. ?????*??
  24. ?????*?@param?args?
  25. ?????*/??
  26. ????public?static?void?main(String[]?args)?{??
  27. ????????runnableDemo();??
  28. ????????futureDemo();??
  29. ????}??
  30. ??
  31. ????/**?
  32. ?????*?runnable,?無返回值?
  33. ?????*/??
  34. ????static?void?runnableDemo()?{??
  35. ??
  36. ????????new?Thread(new?Runnable()?{??
  37. ??
  38. ????????????@Override??
  39. ????????????public?void?run()?{??
  40. ????????????????System.out.println("runnable?demo?:?"?+?fibc(20));??
  41. ????????????}??
  42. ????????}).start();??
  43. ????}??
  44. ??
  45. ????/**?
  46. ?????*?其中Runnable實現的是void?run()方法,無返回值;Callable實現的是?V?
  47. ?????*?call()方法,并且可以返回執行結果。其中Runnable可以提交給Thread來包裝下?
  48. ?????*?,直接啟動一個線程來執行,而Callable則一般都是提交給ExecuteService來執行。?
  49. ?????*/??
  50. ????static?void?futureDemo()?{??
  51. ????????try?{??
  52. ????????????/**?
  53. ?????????????*?提交runnable則沒有返回值,?future沒有數據?
  54. ?????????????*/??
  55. ????????????Future<?>?result?=?mExecutor.submit(new?Runnable()?{??
  56. ??
  57. ????????????????@Override??
  58. ????????????????public?void?run()?{??
  59. ????????????????????fibc(20);??
  60. ????????????????}??
  61. ????????????});??
  62. ??
  63. ????????????System.out.println("future?result?from?runnable?:?"?+?result.get());??
  64. ??
  65. ????????????/**?
  66. ?????????????*?提交Callable,?有返回值,?future中能夠獲取返回值?
  67. ?????????????*/??
  68. ????????????Future<Integer>?result2?=?mExecutor.submit(new?Callable<Integer>()?{??
  69. ????????????????@Override??
  70. ????????????????public?Integer?call()?throws?Exception?{??
  71. ????????????????????return?fibc(20);??
  72. ????????????????}??
  73. ????????????});??
  74. ??
  75. ????????????System.out??
  76. ????????????????????.println("future?result?from?callable?:?"?+?result2.get());??
  77. ??
  78. ????????????/**?
  79. ?????????????*?FutureTask則是一個RunnableFuture<V>,即實現了Runnbale又實現了Futrue<V>這兩個接口,?
  80. ?????????????*?另外它還可以包裝Runnable(實際上會轉換為Callable)和Callable?
  81. ?????????????*?<V>,所以一般來講是一個符合體了,它可以通過Thread包裝來直接執行,也可以提交給ExecuteService來執行?
  82. ?????????????*?,并且還可以通過v?get()返回執行結果,在線程體沒有執行完成的時候,主線程一直阻塞等待,執行完則直接返回結果。?
  83. ?????????????*/??
  84. ????????????FutureTask<Integer>?futureTask?=?new?FutureTask<Integer>(??
  85. ????????????????????new?Callable<Integer>()?{??
  86. ????????????????????????@Override??
  87. ????????????????????????public?Integer?call()?throws?Exception?{??
  88. ????????????????????????????return?fibc(20);??
  89. ????????????????????????}??
  90. ????????????????????});??
  91. ????????????//?提交futureTask??
  92. ????????????mExecutor.submit(futureTask)?;??
  93. ????????????System.out.println("future?result?from?futureTask?:?"??
  94. ????????????????????+?futureTask.get());??
  95. ??
  96. ????????}?catch?(InterruptedException?e)?{??
  97. ????????????e.printStackTrace();??
  98. ????????}?catch?(ExecutionException?e)?{??
  99. ????????????e.printStackTrace();??
  100. ????????}??
  101. ????}??
  102. ??
  103. ????/**?
  104. ?????*?效率底下的斐波那契數列,?耗時的操作?
  105. ?????*??
  106. ?????*?@param?num?
  107. ?????*?@return?
  108. ?????*/??
  109. ????static?int?fibc(int?num)?{??
  110. ????????if?(num?==?0)?{??
  111. ????????????return?0;??
  112. ????????}??
  113. ????????if?(num?==?1)?{??
  114. ????????????return?1;??
  115. ????????}??
  116. ????????return?fibc(num?-?1)?+?fibc(num?-?2);??
  117. ????}??
  118. ??
  119. }??

輸出結果




-------------

更多的Java,Angular,Android,大數據,J2EE,Python,數據庫,Linux,Java架構師,:

http://www.cnblogs.com/zengmiaogen/p/7083694.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538972.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538972.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538972.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sql count為空時顯示0_C0010負坐標顯示為正數+紅色0值參考線

小伙伴們早上好啊&#xff01;今天繼續為大家分享柱形圖的美化技巧。希望大家認真閱讀Excel文件和教程&#xff0c;有的圖表看起來簡單&#xff0c;實際上在細節處理上用了很多技巧&#xff0c;大家要多多體會。C0010-負坐標顯示為正數紅色0值參考線效果圖圖表概述本圖可以用來…

配置IISExpress允許外部訪問

配置IISExpress允許外部訪問 1.找到IISExpress的配置文件&#xff0c;位于 <文檔>/IISExpress/config文件夾下&#xff0c;打開applicationhost.config&#xff0c;找到如下代碼&#xff1a;<site name"WebSite1" id"1" serverAutoStart"tru…

python布爾測試對象_python布爾類型和邏輯運算

布爾類型 python中True表示真&#xff0c;False表示假&#xff0c;它們是布爾類型&#xff1a;1 2>>> type(True) 在python中&#xff0c;bool的True和False是數值1和0的字符串表示格式&#xff0c;實際上bool類型是int類型的一個子類。1 2>>> bool.__bases_…

mac預裝的php路徑,Mac使用系統自帶php和Apache

最美的語言本文將介紹在Mac環境下如何使用系統本身所帶有的Apache(阿帕奇服務器)通過預裝的PHP版本來運行PHP的相關代碼&#xff0c;相對來講在OS X系統下相對好配置一些&#xff0c;因為Apache和PHP都預裝好了&#xff0c;如果是Windows環境我們需要自己安裝ApachePHPMysql(通…

線程池與Callable更配哦

概述 Callable介紹見&#xff1a;http://blog.csdn.net/zengmingen/article/details/53288119 多線程介紹見&#xff1a;http://blog.csdn.net/zengmingen/article/details/53284999 代碼 TaskCallable.javapackage multithreading.pool;import java.util.concurrent.Callabl…

IP編址,IP地址介紹與子網劃分方法

網絡層位于數據鏈路層與傳輸層之間。網絡層中包含了許多協議&#xff0c;其中最為重要的協議就是IP協議。網絡層提供了IP路由功能。理解IP路由除了要熟悉IP協議的工作機制之外&#xff0c;還必須理解IP編址以及如何合理地使用IP地址來設計網絡。 上層協議類型 以太網幀中的Typ…

3- OpenCV+TensorFlow 入門人工智能圖像處理-TensorFlow入門

tensorflow基礎入門 思考一個問題: 如何剛好學習TensorFlow 類比為一門開發語言&#xff0c;學會語法&#xff0c;api的調用&#xff0c; 原理性掌握。語言的要素: 基礎數據類型 運算符 流程 字典 數組 import tensorflow as tf# 常量&#xff0c;指定數據類型 data1 tf.const…

r 函數返回多個值_第四講 R描述性統計分析

在“R與生物統計專題”中&#xff0c;我們會從介紹R的基本知識展開到生物統計原理及其在R中的實現。以從淺入深&#xff0c;層層遞進的形式在投必得醫學公眾號更新。在上一講中&#xff0c;我們介紹了第三講 R編程基礎-矩陣和數據框 (戳這里即可跳轉)。到現在為止&#xff0c;大…

python雙線性插值函數_雙線性插值法原理 python實現

碼字不易&#xff0c;如果此文對你有所幫助&#xff0c;請幫忙點贊&#xff0c;感謝&#xff01;一. 雙線性插值法原理&#xff1a;① 何為線性插值&#xff1f;插值就是在兩個數之間插入一個數&#xff0c;線性插值原理圖如下&#xff1a;在位置 x 進行線性插值&#xff0c;插…

張恩民 php,php100教程_php100張恩民php視頻 56課時_網站編程_寂涯網絡學習基地

1、PHP基本語法和數據類型&#xff1a;(1)、PHP基本語法&#xff1a;1、htm 和 php 混編2、一個語句以 ; (分號結束)3、如何定義一個變量&#xff0c;和變量的使用(2)、PHP數據運算類型四種標量類型&#xff1a;boolean(布爾型)integer(整型)float(浮點型&#xff0c;也作“do…

Oracle 自帶sqldeveloper導入數據到表

步驟 1、建一張字段名和類型與要導入數據一致的表。 2、如果是excel文件&#xff0c;另存為 csv文件。 因為excel文件遇到空格會報錯&#xff0c;excel文件太大工具會讀取文件失敗。 而csv文件是秒級讀取&#xff0c;有空格也會導入不會報錯。 ------------- 更多的Java&am…

百度騰訊中興華為全部入局Linux Foundation深度學習基金會

2019獨角獸企業重金招聘Python工程師標準>>> 雖然名字叫做Linux Foundation&#xff0c;但是這家基金會關注的領域并不局限在Linux操作系統領域。事實上&#xff0c;Linux Foundation基金會還為很多其他開源基金和項目提供支持&#xff0c;比如Cloud Foundry、Autom…

python判斷點在矩形內_判斷平面內矩形和圓是否有交點的python實現

#! /usr/bin/env python# -*- coding: utf-8 -*-filename : 平面坐標內矩形與圓是否相交usage :authors : U{peterguo}copyright: tencentdate : 2012.08.21version : 1.0.0.0Modified History:2012.08.21 創建import osimport sysimport reimport urllib2import timeimport da…

python讀取mysql數據庫_Python操作MySQL數據庫9個實用實例

在Windows平臺上安裝mysql模塊用于Python開發 用python連接mysql的時候&#xff0c;需要用的安裝版本&#xff0c;源碼版本容易有錯誤提示。下邊是打包了32與64版本。 MySQL-python-1.2.3.win32-py2.7.exe MySQL-python-1.2.3.win-amd64-py2.7.exe 實例 1、取得 MYSQL 的版本 #…

win主機上搭建php網站運行環境,Windows server 2008搭建php運行環境圖文詳解(php5.3)

這篇文章主要為大家分享下Windows server 2008搭建php運行環境的步驟&#xff0c;需要的朋友可以參考下下載php組件包首先到http://windows.php.net/download/下載你需要的php版本&#xff0c;這里我下載的是php5.3。下面解壓php組件 包到磁盤上。安裝Microsoft Visual C 2008 …

python 登陸微博 被刪除 token_爬取微博信息,使用了cookie仍然無法登錄微博

按照網上的模板自己寫了類似的代碼爬取微博&#xff0c;可是response回來的html是登錄界面的html&#xff0c;應該是沒有成功登陸微博&#xff0c;但是和網上的代碼是基本一樣的from bs4 import BeautifulSoupimport pandas as pdimport requestsurl "https://weibo.cn/2…

plsql developer連接oracle--本地不安裝oracle

工具 數據庫開發程序 PLSQL Developer oracle 客戶端 instantclient&#xff0c;點擊下載 &#xff08;下載與oracle相同版本或最新版本&#xff0c;如果 PLSQL Developer是32位&#xff0c;則要下載32位的&#xff09;安裝 1、解壓oracle客戶端 到盤某個目錄。我的目錄是C:\or…

ubuntu networking 與 network-manager

剛遇到的坑&#xff0c;因為操作不當導致網絡中斷&#xff0c;于是手動配置了/etc/network/interfaces , 修復了系統之后發現ubuntu-desktop中的有線鏈接不見了&#xff0c;百度了一下說是networking服務和network-manger服務會起沖突。 【Server版本】 在UbuntuServer版本中&…

mysql 升序_mysql 的 查找 與 排序

mysql 的 查找 &#xff1a;SELECT name,age FROM mytable; # 在mytable 中所有的name,age 數據SELECT name,age FROM mytable WHERE age>25; #在mytable 中所有的name,age 數據&#xff0c;其中age必須小于25SELECT name,age FROM mytable WHERE age<25 OR age>30; #…

Hadoop3.0的新特性

轉載&#xff1a;http://blog.csdn.net/sinat_31726559/article/details/52103229 點擊閱讀原文 -------------------------------------- 1. Hadoop3.0簡介 Hadoop 2.0是基于JDK 1.7開發的&#xff0c;而JDK 1.7在2015年4月已停止更新&#xff0c;這直接迫使Hadoop社區基于…