国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

java并發編程學習2--Future

weizx / 625人閱讀

摘要:一個線程池包含很多準備運行的空閑線程,每當執行完畢后,線程不會死亡而是回到線程池準備為下一個請求提供服務。另一個使用線程池的理由是減少并發線程數。創建大量線程會大大降低性能甚至拖垮虛擬機。

【Future的概念

interface Future ,表示異步計算的結果,Future有個get方法而獲取結果只有在計算完成時獲取,否則會一直阻塞直到任務轉入完成狀態,然后會返回結果或者拋出異常。相對于繼承Thread來創建線程方式,使用Runnable可以讓你的實現類同時實現多個接口,而相對于Callable及Future,Runnable方法并不返回任務執行結果且不能拋出異常。

【interface Future 具有如下方法
public interface Future {
    //取消計算,如果尚未開始,直接取消不再運算,如果正在進行:mayInterruptIfRunning等于true就會被中斷。注意一點:只要調用了cancle(),無論任務是否能夠執行,再調用get()都會出現cancledException,這是由于Future.state的狀態被置為CANCELLED = 4,所致的;
    boolean cancel(boolean mayInterruptIfRunning)
    //判斷計算是否取消。
    boolean isCancelled();
    //判斷計算是否完成,如果計算完成返回true,否則返回false
    boolean isDone();
    //獲得異步計算的結果,如果在調用get()的時候結果還沒有計算出來,調用線程將被阻塞。
    V get() throws InterruptedException, ExecutionException;
    //獲得異步計算的結果,如果在調用get()的時候結果還沒有計算出來,調用線程將被阻塞。如果調用超時將會拋出TimeoutException。
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

補充:

   - FutureTask:包裝器,可以將Callable轉換成為Future與Runnable,它同時實現了二者的接口。
   - Callable:可以為異步方法返回計算結果。
   
【下面我們實現一種基于Future的場景
public class Exercise {

       private SimpleApplicationService simpleApplicationService = new SimpleApplicationService();

       @Test
       public void futureTest() throws InterruptedException, ExecutionException {
           long st = System.currentTimeMillis();
           //這里本是一callable接口實現,我用lambda方便一點
           FutureTask result = new FutureTask(() -> simpleApplicationService.query());
           //記住我們的任務都與需要開啟一個新的線程
           Thread t = new Thread(result);
           t.start();
           long end = System.currentTimeMillis();
           System.out.println("耗時:" + (end - st) + " 結果:" + result.get());
       }
   }

   public class SimpleApplicationService {
       public String query() throws InterruptedException {
           System.out.println("開始查詢");
           Thread.sleep(2000);
           return "query result";
       }
   }
【反思一些問題:

每個異步方法都需要新開啟一個線程這樣很消耗資源。

每次都要new一個thread挺麻煩的。

【解決方案:使用線程池

構建一個新的線程是有代價的,因為設計到與操作系統的交互。如果程序中創建了大量的并且生命周期很短的線程,我們應該使用線程池。
一個線程池包含很多準備運行的空閑線程,每當run()執行完畢后,線程不會死亡而是回到線程池準備為下一個請求提供服務。

另一個使用線程池的理由是減少并發線程數。創建大量線程會大大降低性能甚至拖垮虛擬機。

【Executor介紹

Executors類有許多靜態方法可創建線程池。例如:

Executors.newCachedThreadPool():對于一個任務,有空閑線程可用則會立即執行,否則創建一個新的線程??臻e線程存活60s。

Executors.newFixedThreadPool(n):構建具有固定大小的線程池,若任務多余空閑線程數,則將多余任務放置等待隊列中。

Executors.newSingleThreadExecutor():只有一個空閑線程的線程池,任務執行一個接一個;

以上三個方法返回ExecutorService接口的ThreadPoolExecutor對象。

核心(簡介):

ThreadPoolExecutor

    public class ThreadPoolExecutor extends AbstractExecutorService {

        public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
                BlockingQueue workQueue);

        public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
                BlockingQueue workQueue,ThreadFactory threadFactory);

        public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
                BlockingQueue workQueue,RejectedExecutionHandler handler);

        //事實上,前面三個構造器都是調用的第四個構造器進行的初始化工作。
        public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);

    }
    

參數含義:

corePoolSize:核心池的大小,這個參數跟后面講述的線程池的實現原理有非常大的關系。在創建了線程池后,默認情況下,線程池中并沒有任何線程,而是等待有任務到來才創建線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法。從這2個方法的名字就可以看出,是預創建線程的意思,即在沒有任務到來之前就創建corePoolSize個線程或者一個線程。默認情況下,在創建了線程池后,線程池中的線程數為0。當有任務來之后,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中;

maximumPoolSize:線程池最大線程數,這個參數也是一個非常重要的參數,它表示在線程池中最多能創建多少個線程;

keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。默認情況下,只有當線程池中的線程數大于corePoolSize時,keepAliveTime才會起作用。直到線程池中的線程數不大于corePoolSize,即當線程池中的線程數大于corePoolSize時,如果一個線程空閑的時間達到keepAliveTime,則會終止,直到線程池中的線程數不超過corePoolSize。但是如果調用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數不大于corePoolSize時,keepAliveTime參數也會起作用,直到線程池中的線程數為0;

unit:參數keepAliveTime的時間單位

workQueue:一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這里的阻塞隊列有以下幾種選擇:

   - ArrayBlockingQueue
   - LinkedBlockingQueue
   - SynchronousQueue;

threadFactory:線程工廠,主要用來創建線程;

handler:表示當拒絕處理任務時的策略,有以下四種取值:

          - ThreadPoolExecutor.AbortPolicy:丟棄任務并拋出RejectedExecutionException異常。
          - ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。
          - ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)
          - ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務
          

使用連接池應該做的事:

 1. 調用Executors的靜態方法創建線程池。
 2. 調用submit(),提交一個Callable對象或者Runnable對象。
 3. 保存好獲得的Future<>對象,其中是計算結果(如果提交的是Callable)。
 4. 沒有任何任務再提交的時候使用shutDown()。
 

 public class TaskExercise {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //future + callable
            ExecutorService executor = Executors.newCachedThreadPool();
            CallTask callTask = new CallTask();
            Future taskReturn = executor.submit(callTask);
            System.out.println(taskReturn.get());
            //futureTask
            FutureTask futureTask = new FutureTask(callTask);
            executor.submit(futureTask);
            System.out.println(futureTask.get());
            //runable
            Runnable runTask = new RunTask();
            String result = "xz";
            Future runTaskReturn = executor.submit(runTask,result);
            System.out.println(runTaskReturn.get());

            executor.shutdown();
        }
    }
    class CallTask implements Callable{
        @Override
        public String call() throws Exception {
            return "task return";
        }
    }
    class RunTask implements Runnable{
        @Override
        public void run() {
            System.out.println("run");
        }
    }
    
【控制任務組

有時使用執行器更有意義的場景是控制一組相關任務。

1. shutdownNow():取消所有任務
2. invokeAny():提交所有對象到一個Callable對象集合,并返回某個已完成的任務結果。例如:如果你愿意接受任何一種解決方案的話。
3. 還有其他一些方法等我們真正用到時再學習好了~
【補充

spring中實現異步調用:spring為任務調度與異步方法執行提供了注解支持。通過在方法上設置@Async注解,可使得方法被異步調用。也就是說調用者會在調用時立即返回,而被調用方法的實際執行是交給Spring的TaskExecutor來完成。如果是有返回值的話記得:接口返回Future<>,實現返回AsyncResult<>。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70902.html

相關文章

  • Java 多線程并發編程面試筆錄一覽

    摘要:創建線程的方式方式一將類聲明為的子類。將該線程標記為守護線程或用戶線程。其中方法隱含的線程為父線程?;謴途€程,已過時。等待該線程銷毀終止。更多的使當前線程在鎖存器倒計數至零之前一直等待,除非線 知識體系圖: showImg(https://segmentfault.com/img/bVbef6v?w=1280&h=960); 1、線程是什么? 線程是進程中獨立運行的子任務。 2、創建線...

    bitkylin 評論0 收藏0
  • 2018年第18周-Java語言思想-并發

    摘要:某些編程語言被設計為可以將并發任務彼此隔離,這些語言通常被稱為函數性語言。通過使用多線程機制,這些獨立任務也被稱為子任務中的每一個都將由執行線程來驅動。 并發 之前學的都是順序編程的知識,學習并發編程就好像進入了一個全新的領域,有點類似于學習了一門新的編程語言,或者至少是學習了一整套新的語言概念。要理解并發編程,其難度與理解面向對象編程差不多。如果花點兒功夫,就能明白其基本機制,但想要...

    JouyPub 評論0 收藏0
  • Java并發

    摘要:對象改變條件對象當前線程要等待線程終止之后才能從返回。如果線程在上的操作中被中斷,通道會被關閉,線程的中斷狀態會被設置,并得到一個。清除線程的中斷狀態。非公平性鎖雖然可能造成饑餓,但極少的線程切換,保證其更大的吞吐量。 聲明:Java并發的內容是自己閱讀《Java并發編程實戰》和《Java并發編程的藝術》整理來的。 showImg(https://segmentfault.com/im...

    SKYZACK 評論0 收藏0
  • Java多線程學習(七)并發編程中一些問題

    摘要:相比與其他操作系統包括其他類系統有很多的優點,其中有一項就是,其上下文切換和模式切換的時間消耗非常少。因為多線程競爭鎖時會引起上下文切換。減少線程的使用。很多編程語言中都有協程。所以如何避免死鎖的產生,在我們使用并發編程時至關重要。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)syn...

    dingding199389 評論0 收藏0
  • Java多線程學習(七)并發編程中一些問題

    摘要:因為多線程競爭鎖時會引起上下文切換。減少線程的使用。舉個例子如果說服務器的帶寬只有,某個資源的下載速度是,系統啟動個線程下載該資源并不會導致下載速度編程,所以在并發編程時,需要考慮這些資源的限制。 最近私下做一項目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Jav...

    yimo 評論0 收藏0

發表評論

0條評論

weizx

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<