1. 程式人生 > >Java多執行緒之Callable介面與Runnable的實現以及選擇

Java多執行緒之Callable介面與Runnable的實現以及選擇

通過實現Runnable介面的實現

package Thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RunnableThreadDemo {

private static int POOL_NUM = 30; // 執行緒池數量

public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < POOL_NUM; i++) {
RunnableThread thread = new RunnableThread();
//執行緒停頓
Thread.sleep(1000);
executorService.execute(thread);
}
// 關閉執行緒池
executorService.shutdown();
}

}

class RunnableThread implements Runnable {
@Override
public void run() {
System.out.println("通過執行緒池方式建立的執行緒Runnable方式:" + Thread.currentThread().getName() + " ");
}
}
通過實現Runnable介面的實現

package Thread;

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 CallableThreadDemo {

private static int POOL_NUM = 30; // 執行緒池數量

public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < POOL_NUM; i++) {
Callable<Integer> callableThread = new CallableThread();

FutureTask<Integer> thread = new FutureTask<Integer>(callableThread);
//執行緒停頓
Thread.sleep(1000);
//執行 Callable 方式,需要 FutureTask 實現類的支援,用於接收運算結果。 FutureTask 是 Future 介面的實現類
executorService.submit(thread);

System.out.println(thread.get());
}
// 關閉執行緒池
executorService.shutdown();
}
}

class CallableThread implements Callable<Integer> {

@Override
public Integer call() throws Exception {
System.out.println("通過執行緒池方式建立的執行緒Callable方式:" + Thread.currentThread().getName() + " ");
return 10086;
}
}

  1.Callable規定的方法是call(),而Runnable規定的方法是run().
  2.Callable的任務執行後可返回值,而Runnable的任務是不能返回值的。  
  3.call() 方法可丟擲異常,而run() 方法是不能丟擲異常的。 
  4.執行Callable任務可拿到一個Future物件, Future表示非同步計算的結果。 
  5.它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。 
  6.通過Future物件可瞭解任務執行情況,可取消任務的執行,還可獲取任務執行的結果。
  7.Callable是類似於Runnable的介面,實現Callable介面的類和實現Runnable的類都是可被其它執行緒執行的任務。  

       ExecutorService、Callable都是屬於Executor框架。返回結果的執行緒是在JDK1.5中引入的新特徵,還有Future介面也是屬於這個框架,有了這種特徵得到返回值就很方便了。 
通過分析可以知道,他同樣也是實現了Callable介面,實現了Call方法,所以有返回值。這也就是正好符合了前面所說的兩種分類

       執行Callable任務後,可以獲取一個Future的物件,在該物件上呼叫get就可以獲取到Callable任務返回的Object了。get方法是阻塞的,即:執行緒無返回結果,get方法會一直等待。

再介紹Executors類:提供了一系列工廠方法用於建立執行緒池,返回的執行緒池都實現了ExecutorService介面。

public static ExecutorService newFixedThreadPool(int nThreads) 
建立固定數目執行緒的執行緒池。
public static ExecutorService newCachedThreadPool() 
建立一個可快取的執行緒池,呼叫execute 將重用以前構造的執行緒(如果執行緒可用)。如果現有執行緒沒有可用的,則建立一個新執行緒並新增到池中。終止並從快取中移除那些已有 60 秒鐘未被使用的執行緒。
public static ExecutorService newSingleThreadExecutor() 
建立一個單執行緒化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int 
corePoolSize) 
建立一個支援定時及週期性的任務執行的執行緒池,多數情況下可用來替代Timer類。
ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor後臺執行緒池還沒有完成Callable的計算,這呼叫返回Future物件的get()方法,會阻塞直到計算完成。
 

為什麼要用執行緒池:

1.減少了建立和銷燬執行緒的次數,每個工作執行緒都可以被重複利用,可執行多個任務。

2.可以根據系統的承受能力,調整執行緒池中工作線執行緒的數目,防止因為消耗過多的記憶體,而把伺服器累趴下(每個執行緒需要大約1MB記憶體,執行緒開的越多,消耗的記憶體也就越大,最後宕機)。

Java裡面執行緒池的頂級介面是Executor,但是嚴格意義上講Executor並不是一個執行緒池,而只是一個執行執行緒的工具。真正的執行緒池介面是ExecutorService。

題外話,Thread表示一個執行緒,每個任務都建立一個執行緒肯定是不妥的,正確的做法應該是初始化一定量的Thread物件,實現Runnable介面建立表示任務的類,並把這些任務對給Thread執行緒執行。

 
我們應該是使用Runnable還是Thread?
Java不支援多繼承,但允許實現多個介面。所以如果需要繼承其他類,實現Runnable介面是好了。
---------------------
作者:性情中人1993
來源:CSDN
原文:https://blog.csdn.net/qq_38765404/article/details/81163959
版權宣告:本文為博主原創文章,轉載請附上博文連結!