㈠ java future函數的作用
在並發編程時,一般使用runnable,然後扔給線程池完事,這種情況下不需要線程的結果。
所以run的返回值是void類型。
如果是一個多線程協作程序,比如菲波拉切數列,1,1,2,3,5,8...使用多線程來計算。
但後者需要前者的結果,就需要用callable介面了。
callable用法和runnable一樣,信襪只不過調用的是call方法,該方法有一個泛型返回值類型,你可以任意指定。
線程是帆坦薯屬於非同步計算模型,所以你不可能直接從別的線程中得到函數返回值。
這時候,Future就出場了。Futrue可以監視目標線程調用call的情況,當你調用Future的get()方法以獲得結果時,當前線態者程就開始阻塞,直接call方法結束返回結果。
㈡ ExecutorService中submit和execute的區別
ExecutorService中submit和execute的區別有三點:
1、接收的參數不同
2、submit有返回值,而execute沒有
用到返回值的例子,比如說應用中有很多個做validation的task,用戶希望所有的task執行完,然後每個task告訴主程序執行結果,是成功還是失敗,如果是失敗攔鬧,原因是什麼。然後就可以把所有失敗的原因綜合起來發給調用者。
3、submit方便Exception處理,而execute處理異常比較麻煩。
在task里會拋出checked或者unchecked exception,而用戶又希望外面的調用者能夠感知這些exception並做出及時的處理,那麼就需要用到submit,通過捕獲Future.get拋出的異常。
舉例說明:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorServiceTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 創建10個任務並執行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService執行Callable類型的任務,並將結果保存在future變數中
Future<String> future = executorService.submit(new TaskWithResult(i));
// 將任務執行結果殲罩存儲到List中
resultList.add(future);
}
executorService.shutdown();
// 遍歷任務的結果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); // 列印各個線程(任務)執行的結簡改罩果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
executorService.shutdownNow();
e.printStackTrace();
return;
}
}
}
}
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
/**
* 任務的具體過程,一旦任務傳給ExecutorService的submit方法,則該方法自動在一個線程上執行。
*
* @return
* @throws Exception
*/
public String call() throws Exception {
System.out.println("call()方法被自動調用,幹活!!! " + Thread.currentThread().getName());
if (new Random().nextBoolean())
throw new TaskException("Meet error in task." + Thread.currentThread().getName());
// 一個模擬耗時的操作
for (int i = 999999999; i > 0; i--)
;
return "call()方法被自動調用,任務的結果是:" + id + " " + Thread.currentThread().getName();
}
}
class TaskException extends Exception {
public TaskException(String message) {
super(message);
}
}
執行的結果類似於:
call()方法被自動調用,幹活!!! pool-1-thread-1
call()方法被自動調用,幹活!!! pool-1-thread-2
call()方法被自動調用,幹活!!! pool-1-thread-3
call()方法被自動調用,幹活!!! pool-1-thread-5
call()方法被自動調用,幹活!!! pool-1-thread-7
call()方法被自動調用,幹活!!! pool-1-thread-4
call()方法被自動調用,幹活!!! pool-1-thread-6
call()方法被自動調用,幹活!!! pool-1-thread-7
call()方法被自動調用,幹活!!! pool-1-thread-5
call()方法被自動調用,幹活!!! pool-1-thread-8
call()方法被自動調用,任務的結果是:0 pool-1-thread-1
call()方法被自動調用,任務的結果是:1 pool-1-thread-2
java.util.concurrent.ExecutionException: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.cicc.pts.ExecutorServiceTest.main(ExecutorServiceTest.java:29)
Caused by: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:57)
at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
㈢ Java多線程是什麼意思
Java多線程實現方式主要有三種:繼承Thread類、實現Runnable介面、使用ExecutorService、Callable、Future實現有返回結果的多線程。其中前兩種方式線程執行完後都沒有返回值,只有最後一種是帶返回值的。
1、繼承Thread類實現多線程
繼承Thread類的方法盡管被我列為一種多線程實現方式,但Thread本質上也是實現了Runnable介面的一個實例,它代表一個線程的實例,並且,啟動線程的唯一方法就是通過Thread類的start()實例方法。start()方法是一個native方法,它將啟動一個新線程,並執行run()方法。這種方式實現多線程很簡單,通過自己的類直接extend Thread,並復寫run()方法,就可以啟動新線程並執行自己定義的run()方法。例如:

代碼說明:
上述代碼中Executors類,提供了一系列工廠方法用於創先線程池,返回的線程池都實現了ExecutorService介面。
public static ExecutorService newFixedThreadPool(int nThreads)
創建固定數目線程的線程池。
public static ExecutorService newCachedThreadPool()
創建一個可緩存的線程池,調用execute 將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程並添加到池中。終止並從緩存中移除那些已有 60 秒鍾未被使用的線程。
public static ExecutorService newSingleThreadExecutor()
創建一個單線程化的Executor。
public static ScheledExecutorService newScheledThreadPool(int corePoolSize)
創建一個支持定時及周期性的任務執行的線程池,多數情況下可用來替代Timer類。
總結:ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor後台線程池還沒有完成Callable的計算,這調用返回Future對象的get()方法,會阻塞直到計算完成。
㈣ java項目中很多地方使用線程池,線上伺服器內存佔用越來越大.每個線程佔用8.8M.問題是哪兒
針對你說的這種情況,可以使用jvisualvm.exe直接查看內存使用情況,查看是否是有大對象。
㈤ java並發包有哪些類
1、
一個同步輔助類,允許一組線程相互等待,直到這組線程都到達某個公共屏障點。該barrier在釋放等待線程後可以重用,因此稱為循環的barrier。
來個示例:
[java]view plain
packagetest;
importjava.util.concurrent.CyclicBarrier;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassRecipes_CyclicBarrier{
=newCyclicBarrier(10);
publicstaticvoidmain(String[]args){
ExecutorServiceexecutor=Executors.newCachedThreadPool();//FixedThreadPool(10);
for(inti=1;i<=10;i++){
executor.submit(newThread(newRunner(i+"號選手")));
}
executor.shutdown();
}
}
classRunnerimplementsRunnable{
privateStringname;
publicRunner(Stringname){
this.name=name;
}
@Override
publicvoidrun(){
System.out.println(name+"准備好了。");
try{
Recipes_CyclicBarrier.barrier.await();//此處就是公共屏障點,所有線程到達之後,會釋放所有等待的線程
}catch(Exceptione){
}
System.out.println(name+"起跑!");
}
}
2、CountDownLatch
CountDownLatch和CyclicBarrier有點類似,但是還是有些區別的。CountDownLatch也是一個同步輔助類,它允許一個或者多個線程一直等待,直到正在其他線程中執行的操作完成。它是等待正在其他線程中執行的操作,並不是線程之間相互等待。CountDownLatch初始化時需要給定一個計數值,每個線程執行完之後,必須調用countDown()方法使計數值減1,直到計數值為0,此時等待的線程才會釋放。
來個示例:
[java]view plain
packagetest;
importjava.util.concurrent.CountDownLatch;
importjava.util.concurrent.CyclicBarrier;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassCountDownLatchDemo{
=newCountDownLatch(10);//初始化計數值
publicstaticvoidmain(String[]args){
ExecutorServiceexecutor=Executors.newCachedThreadPool();//FixedThreadPool(10);
for(inti=1;i<=10;i++){
executor.submit(newThread(newRunner1(i+"號選手")));
}
executor.shutdown();
}
}
{
privateStringname;
publicRunner1(Stringname){
this.name=name;
}
@Override
publicvoidrun(){
System.out.println(name+"准備好了。");
CountDownLatchDemo.countDownLatch.countDown();//計數值減1
try{
CountDownLatchDemo.countDownLatch.await();
}catch(Exceptione){
}
System.out.println(name+"起跑!");
}
}
3、CopyOnWriteArrayList & CopyOnWriteArraySet
CopyOnWriteArrayList & CopyOnWriteArraySet是並發容器,適合讀多寫少的場景,如網站的黑白名單設置。缺點是內存佔用大,數據一致性的問題,CopyOnWrite容器只能保證數據最終的一致性,不能保證數據實時一致性。鑒於它的這些缺點,可以使用ConcurrentHashMap容器。
實現原理:新增到容器的數據會放到一個新的容器中,然後將原容器的引用指向新容器,舊容器也會存在,因此會有兩個容器佔用內存。我們也可以用同樣的方式實現自己的CopyOnWriteMap。
4、ConcurrentHashMap
ConcurrentHashMap同樣是一個並發容器,將同步粒度最小化。
實現原理:ConcurrentHashMap默認是由16個Segment組成,每個Segment由多個Hashtable組成,數據變更需要經過兩次哈希演算法,第一次哈希定位到Segment,第二次哈希定位到Segment下的Hashtable,容器只會將單個Segment鎖住,然後操作Segment下的Hashtable,多個Segment之間不受影響。如果需要擴容不是對Segment擴容而是對Segment下的Hashtable擴容。雖然經過兩次哈希演算法會使效率降低,但是比鎖住整個容器效率要高得多。
5、BlockingQueue
BlockingQueue只是一個介面,它的實現類有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue、LinkedBlockingDeque。
ArrayBlockingQueue:由數據支持的有界阻塞隊列。
LinkedBlockingQueue:基於鏈接節點、范圍任意的阻塞隊列。
PriorityBlockingQueue:無界阻塞隊列。
SynchronousQueue:一種阻塞隊列,其中每個插入操作必須等待另一個線程的對應移除操作。
DelayQueue:Delayed元素的一個無界阻塞隊列。
LinkedBlockingDeque:基於鏈接節點、范圍任意的雙端阻塞隊列,可以在隊列的兩端添加、移除元素。
6、Lock
Lock分為公平鎖和非公平鎖,默認是非公平鎖。實現類有ReetrantLock、ReetrantReadWriteLock,都依賴於AbstractQueuedSynchronizer抽象類。ReetrantLock將所有Lock介面的操作都委派到Sync類上,Sync有兩個子類:NonFairSync和FaiSync,通過其命名就能知道分別處理非公平鎖和公平鎖的。AbstractQueuedSynchronizer把所有請求構成一個CLH隊列,這里是一個虛擬隊列,當有線程競爭鎖時,該線程會首先嘗試是否能獲取鎖,這種做法對於在隊列中等待的線程來說是非公平的,如果有線程正在Running,那麼通過循環的CAS操作將此線程增加到隊尾,直至添加成功。
7、Atomic包
Atomic包下的類實現了原子操作,有對基本類型如int、long、boolean實現原子操作的類:AtomicInteger、AtomicLong、AtomicBoolean,如果需要對一個對象進行原子操作,也有對對象引用進行原子操作的AtomicReference類,還有對對象數組操作的原子類:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。原子操作核心思想是CAS操作,然後調用底層操作系統指令來實現。
㈥ java中ExecutorService的線程池如何暫停所有的任務和繼續所有的任務 有這樣的函數嗎
Executor 提供了管理終止的方法,以及可為跟蹤一個或多個非同步任務執行狀況而生成 Future 的方法。
可以關閉 ExecutorService,這將導致其拒絕新任務。提供兩個方法來關閉 ExecutorService。shutdown() 方法在終止前允許執行以前提交的任務,而 shutdownNow() 方法阻止等待任務啟動並試圖停止當前正在執行的任務。在終止時,執行程序沒有任務在執行,也沒有任務在等待執行,並且無法提交新任務。應該關閉未使用的 ExecutorService 以允許回收其資源。
通過創建並返回一個可用於取消執行和/或等待完成的 Future,方法 submit 擴展了基本方法 Executor.execute(java.lang.Runnable)。方法 invokeAny 和 invokeAll 是批量執行的最常用形式,它們執行任務 collection,然後等待至少一個,或全部任務完成(可使用 ExecutorCompletionService 類來編寫這些方法的自定義變體)。
Executors 類提供了用於此包中所提供的執行程序服務的工廠方法。
㈦ java 如何創建一個有返回值的線程
可以通過實現Callable介面創建一個有返回值的線程,代碼如下:
importjava.util.concurrent.*;
<Integer>{
privateintcount;
publicMyThread(intcount){
this.count=count;
}
@Override
publicIntegercall()throwsException{
//此處是線程要處理的業務代碼,此處實現的是對count變數加1的操作
count+=1;
Thread.sleep(1000);
returncount;
}
publicstaticvoidmain(String[]args){
//創建線程實例
MyThreadmyThread=newMyThread(1);
//創建一個大小為10的線程池
ExecutorServiceexecutor=Executors.newFixedThreadPool(10);
//將線程提交到線程池執行
Future<Integer>future=executor.submit(myThread);
try{
//調用get方法獲取線程執行結果,在線程執行完成前該方法會一直阻塞
Integerresult=future.get();
System.out.println(result);
}catch(InterruptedExceptione){
e.printStackTrace();
}catch(ExecutionExceptione){
e.printStackTrace();
}
//try{
////這種寫法可以設置線程執行的超時時間,當線程超過指定的時間還未執行完成時會拋出TimeoutException異常
////示例中表示線程超過1000毫秒還沒執行完就會拋出超時異常
//Integerresult=future.get(1000,TimeUnit.MILLISECONDS);
//System.out.println(result);
//}catch(InterruptedExceptione){
//e.printStackTrace();
//}catch(ExecutionExceptione){
//e.printStackTrace();
//}catch(TimeoutExceptione){
//e.printStackTrace();
//}
}
}
㈧ 非同步多線程----執行器(Executor)
如果 程序中創建了大量的生命期很短的線程 ,應該 使用線程池(thread pool) 。一個線程池中包含許多准備運行的空線程。將Runnable對象交給線程池,就會有一個線程調用run方法。當run方法退出時,線游枯程不會死亡,而是在池中准備為下一個請求提供服務。
另一個使用線程池的理由是減少並發線程的數目 。 創建大量線程會大大降低性能甚至使虛擬機崩潰 。如果有一個會創建許多線程的演算法, 應該使用一個線程數「固定的」線程池 以限制並發線程的總數。
執行器(Executor)類有許多靜態工廠方法用來構建線程池。
上面3個方法返回實現了ExecutorService介面 的 ThreadPoolExecutor類的對象 。
可以使用下面的方法 將一個Runnable對象或Callable對象提交給ExecutorService :
該線程池會在方便的時候盡早執行提交的任務。 調用submit時 , 會得到一個Future對象 ,可用來查詢該任務的狀態。
第一個submit方法返回一個Future<?>。可以使用這樣一個對象來調用isDone、cancel或isCancelled。但是,get方法在完成的時候只是簡單地返回null。
第二版本的Submit也提交一個Runnable,並且Future的get方法在完成的神哪洞時候返回指定的result對象。
第三個版本的Submit提交一個Callable,並且返回的Future對象將在計算結構准備好的時候得到它。
當用完一個線程池的時候,調用shutdown 。該方法 啟動該池的關緩滾閉序列 。被關閉的執行器 不再接受新的任務 。當 所有任務都完成以後,線程池中的線程死亡 。另一種方法是調用 shutdownNow 。該池 取消尚未開始的所有任務並試圖中斷正在運行的線程 。
總結在使用線程池時應該做的事:
繼續以一個計算匹配的文件數目程序為例:
ScheledExecutorService介面 具有 為預定執行 (Scheled Execution)或 重復執行任務而設計 的方法。它是一種允許使用線程池機制的java.util.Timer的泛化。Executors類的 newScheledThreadPool 和 方法 將返回實現了ScheledExecutorService介面的對象。
可以預定Runnable或Callable在初始的延遲之後只運行一次。也可以預定一個Runnable對象周期性地運行。詳見API。
㈨ 如何在java中獲取線程非同步執行之後的結果
java中提供了Future<V>介面和實現了Future介面的FutureTask<V> 類來將線程執行之後的結果返回(通過get()方法)。
1.Future<V>介面
Runnable介面執行任務是不返回任何值的,Runnable的run()方法的執行結果是void,而Future介面的call方法是有返回結果的,這是Runnable跟Future的區別之一,它們的另一個不同之處就是實現了Runnable介面的任務執行是調用ExecutorService的execute(Runnable task)方法,而實現了Future介面的任務是調用ExecutorService的submit(Future task)方法。調用Future的get()方法就能直接得到任務的返回值,該方法會一直阻塞直到任務的結果出來為止,我們可以調用Future的isDone()方法來判斷該任務的結果是否准備就緒。
[java] view plain
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestFuture {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newCachedThreadPool();
Future result1 = executor.submit(new Callable() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
});
Future result2 = executor.submit(new Callable() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 10; i < 100; i++) {
sum += i;
}
return sum;
}
});
executor.shutdown();
System.out.println(result1.get() + result2.get());
}
}
2.FutureTask類
FutureTask實現了Future介面,將一個Callable實例作為參數傳給它,就能創建一個FutureTask實例,然後用ExecutorService的submit方法來執行這個實例。最後同樣是用get方法獲取線程執行後的結果。
[plain] view plain
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class TestFutureTask {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newCachedThreadPool();
Callable task = new Callable() {
@Override
public String call() throws Exception {
return "結果";
}
};
FutureTask ft = new FutureTask(task);
executor.submit(ft);
System.out.println(ft.get());
executor.shutdown();
}
}empty
㈩ 在java中executor和executors的區別
它是"執行者"介面,它是來執行任務的。准確的說,Executor提供了execute()介面蠢孫來執行已提交的 Runnable 任務的對象。Executor存帶態鏈在的目的是提供一種將"任務提交閉擾"與"任務如何運行"分離開來的機制。它只包含一個函數介面。
2. Executors
Executors是個靜態工廠類。它通過靜態工廠方法返回ExecutorService、ScheledExecutorService、ThreadFactory 和 Callable 等類的對象。
3. ExecutorService
ExecutorService繼承於Executor。它是"執行者服務"介面,它是為"執行者介面Executor"服務而存在的;准確的話,ExecutorService提供了"將任務提交給執行者的介面(submit方法)","讓執行者執行任務(invokeAll, invokeAny方法)"的介面等等。