溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java Executor框架怎么用

發(fā)布時間:2022-01-17 16:01:42 來源:億速云 閱讀:88 作者:iii 欄目:編程語言

這篇文章主要介紹“Java Executor框架怎么用”,在日常操作中,相信很多人在Java Executor框架怎么用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java Executor框架怎么用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

大多數(shù)并發(fā)都是通過任務執(zhí)行的方式來實現(xiàn)的。一般有兩種方式執(zhí)行任務:串行和并行。

class SingleThreadWebServer {     public static void main(String[] args) throws Exception {         ServerSocket socket = new ServerSocket(80);         while(true) {             Socket conn = socket.accept();             handleRequest(conn);         }     } }  class ThreadPerTaskWebServer {     public static void main(String[] args) throws Exception {         ServerSocket socket = new ServerSocket(80);         while(true) {             final Socket conn = socket.accept();             Runnable task = new Runnable() {                 public void run() {                     handleRequest(conn);                 }             };             new Thread(task).start();         }     } }

當然上面的這兩種方式都是有問題的。單線程的問題就是并發(fā)量會是瓶頸,多線程版本就是***制的創(chuàng)建線程會導致資源不足問題。

Executor 框架

任務是一組邏輯工作單元,而線程是使任務異步執(zhí)行的機制。

JDK 提供了 Executor 接口:

public interface Executor {     void execute(Runnable command); }

雖然 Executor  接口比較簡單,但是卻是異步任務執(zhí)行框架的基礎,該框架能支持多種不同類型的任務執(zhí)行策略。它提供了一種標準的方式把任務的提交過程與執(zhí)行過程進行了解 耦。用 Runnable 來代表任務。Executor 的實現(xiàn)提供了對生命周期的支持以及統(tǒng)計信息應用程序管理等機制。

Executor 是基于生產(chǎn)者消費者模式的,提交任務的操作相當于生產(chǎn)者,執(zhí)行任務的線程相當于消費。

基于 Executor 的 WebServer 例子如下:

public class TaskExecutorWebServer {     private static final int NTHREADS = 100;     private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);      public static void main(String[] args) throws Exception {         ServerSocket serverSocket = new ServerSocket(80);         while (true) {             final Socket conn = serverSocket.accept();             Runnable task = new Runnable() {                 @Override                 public void run() {                     handleRequest(conn);                 }             };             exec.execute(task);         }     } }

另外可以自己實現(xiàn) Executor 來控制是并發(fā)還是并行的,如下面代碼:

/** * 執(zhí)行已提交的 Runnable 任務的對象。 * 此接口提供一種將任務提交與每個任務將如何運行的機制(包括線程使用的細節(jié)、調(diào)度等)分離開來的方法。 * 通常使用 Executor 而不是顯式地創(chuàng)建線程。 * * * @author renchunxiao * */ public class ExecutorDemo {     public static void main(String[] args) {         Executor executor = new ThreadExecutor();         executor.execute(new Runnable() {             @Override             public void run() {                 // do something             }         });          Executor executor2 = new SerialExecutor();         executor2.execute(new Runnable() {             @Override             public void run() {                 // do something             }         });      } }  /** * 創(chuàng)建一個線程來執(zhí)行 command * * @author renchunxiao * */ class ThreadExecutor implements Executor {     @Override     public void execute(Runnable command) {         new Thread(command).start();     } }  /** * 串行執(zhí)行 command * * @author renchunxiao * */ class SerialExecutor implements Executor {     @Override     public void execute(Runnable command) {         command.run();     } }

線程池

線程池就是線程的資源池,可以通過 Executors 中的靜態(tài)工廠方法來創(chuàng)建線程池。

  • newFixedThreadPool。創(chuàng)建固定長度的線程池,每次提交任務創(chuàng)建一個線程,直到達到線程池的***數(shù)量,線程池的大小不再變化。

  • newSingleThreadExecutor。單個線程池。

  • newCachedThreadPool。根據(jù)任務規(guī)模變動的線程池。

  • newScheduledThreadPool。創(chuàng)建固定長度的線程池,以延遲或定時的方式來執(zhí)行任務。

JVM 只有在所有非守護線程全部終止后才會退出,所以,如果無法正確的關閉 Executor,那么 JVM 就無法結束。

為了解決執(zhí)行服務的生命周期問題,有個擴展 Executor 接口的新接口 ExecutorService。

public interface ExecutorService extends Executor {      void shutdown();      List<Runnable> shutdownNow();      boolean isShutdown();      boolean isTerminated();      boolean awaitTermination(long timeout, TimeUnit unit)         throws InterruptedException;      <T> Future<T> submit(Callable<T> task);      <T> Future<T> submit(Runnable task, T result);      Future<?> submit(Runnable task);      <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)         throws InterruptedException;      <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,                                   long timeout, TimeUnit unit)         throws InterruptedException;      <T> T invokeAny(Collection<? extends Callable<T>> tasks)         throws InterruptedException, ExecutionException;      <T> T invokeAny(Collection<? extends Callable<T>> tasks,                     long timeout, TimeUnit unit)         throws InterruptedException, ExecutionException, TimeoutException; }

ExecutorService 生命周期有三種狀態(tài):運行、關閉、已終止。ExecutorService  在初始創(chuàng)建時處于運行狀態(tài)。shutdown  方法會平緩關閉:不在接受新的任務,并且等待已經(jīng)執(zhí)行的任務執(zhí)行完成(包括那些還未開始的任務)。shutdownNow  方法將粗暴關閉:它將嘗試取消所有運行中的任務,并且不再啟動隊列中尚未開始的任務。所有任務都執(zhí)行完成后進入到已終止狀態(tài)。

Callable 和 Future

Executor 框架使用 Runnable 作為基本的任務表示形式。Runnable 是一種有局限性的抽象,它的 run 方法不能返回值和拋出一個受檢查異常。

許多任務實際上是存在延時的計算,例如數(shù)據(jù)庫查詢,從網(wǎng)絡獲取資源。對于這些任務,Callable 是更好的抽象,它認為 call 將返回一個值,并且可能拋出異常。

Executor 執(zhí)行的任務有四個生命周期階段:創(chuàng)建、提交、開始和完成。由于有些任務需要很長時間有可能希望取消,在 Executor 框架當中,已提交未開始的任務可以取消。

Future 表示一個任務的生命周期,并且提供了相應的方法來判斷是否已經(jīng)完成或取消,以及獲取任務的結果和取消任務等。

到此,關于“Java Executor框架怎么用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI