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

資訊專欄INFORMATION COLUMN

Java 線程池

ctriptech / 890人閱讀

系統啟動一個線程的成本是比較高,使用線程池可以很好地提高性能,尤其是當程序中需要創建大量生存期很短暫的線程時

線程池在系統啟動時即創建大量空閑線程,將一個Runnable、Callable對象—–>傳給線程池—–>線程池啟動里面的一個線程來執行它們的run()或者call()方法———->當線程執行體執行完成后,線程并不會死亡,而是再次返回線程池成為空閑狀態,等待下一個Runnable、Callable對象的run()或者call()方法

Java8改進的線程池 Executors工廠類

Java5開始,Java內建支持線程池。Executors工廠類來產生線程池,該工廠類包含如下幾個靜態工廠方法來創建線程池:

ExecutorService newCachedThreadPool():創建一個具有緩存功能的線程池,系統根據需要創建線程,這些線程將會被緩存在線程池中

ExecutorService newFixedThreadPool(int nThreads):創建一個可重用的、具有nThread個固定的線程的線程池

ExecutorService newSingleThreadExecutor():創建包含一個只有單線程的線程池,相當于調用newFixedThreadPool(1)

ScheduledExecutorService newScheduledThreadPool(int corePoolSize):創建具有指定線程數量的線程池,可以在指定延遲后執行線程任務。corePoolSize指池中所保存的線程數,即使線程是空閑的也被保存在線程池內

ScheduledExecutorService newSingleThreadScheduledExecutor():創建只有一個線程的線程池,可以指定延遲后執行線程任務

ExecutorService newWorkStealingPool(int parallelism):創建持有足夠的線程的線程池來支持給定的并行級別,該方法還會使用多個隊列來減少競爭

ExecutorService newWorkStealingPool():該方法可以看做是前一個方法的簡本,并行級別不需要用戶手工指定,是根據計算機CPU個數自動生成的,如果當前機器有6個CPU,則調用該方法時并行級別被設為6

前三個方法返回一個ExecutorService對象,代表一個線程池,可以執行Runnable對象和Callable對象所代表的線程;中間兩個方法返回一個ScheduledExecutorService對象,它是ExecutorService的子類,可以在指定延遲后執行線程任務;最后兩個方法生成的work stealing池,相當于后臺線程池,如果所有的前臺線程都死亡了,work stealig池中的線程也會自動死亡

ExecutorService

ExecutorService代表盡快執行線程的線程池(只要線程中有空閑線程就立即執行線程任務),程序只要將一個Runnable對象或Callable對象(代表線程任務)提交給該線程池,該線程池就會盡快執行該任務

ExecutorService里提供了如下3個方法:

Future submit(Runnable task):將一個Runnable對象提交給指定的線程池,線程池將在有空閑線程時執行Runnable對象代表的任務。其中Future對象代表Runnable任務的返回值——但是run()方法沒有返回值,所以Future對象將在run()方法執行結束后返回null。但可以調用Future的isDone()、isCancelled()方法來獲得Runnable對象的執行狀態

Future submit(Runnable task, T result):將一個Runnable對象提交給指定的線程池,線程池將在有空閑線程時執行Runnable對象代表的任務。其中result顯式指定線程執行結束后的返回值,所以Future對象將在run()方法執行后返回result

Future submit(Callable task):將一個Callable對象提交給指定的線程池,線程池將在有空閑線程時執行Callable對象代表的任務。其中Future代表Callable對象里call()方法的返回值

ScheduledExecutorService

ScheduledExecutorService代表可在指定延遲后或周期性地執行線程任務的線程池,這提供了如下4個方法:

ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit):指定Callable任務將在delay延遲后執行

ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit):指定Command任務將在delay延遲后執行

ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):指定command任務將在delay延遲后執行,而且以設定頻率重復執行。即initialDelay后開始執行,依次在initialDelay + period、initialDelay + 2*period...處重復執行

ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay,long delay,TimeUnit unit):創建并執行一個在給定初始延遲后首次啟動的定期操作,隨后在每一次執行終止和下一次執行開始之間都存在給定的延遲。如果任務在任一次執行時遇到異常,就會取消后續執行,否則,只能通過程序來顯式取消或終止該任務

使用線程池來執行線程任務

當用完一個線程池后,應該調用該線程池的shutdown()方法,該方法將啟動線程池的關閉序列,調用shutdown()方法后的線程池不再接收新任務,但會將以前所有已提交的任務執行完成。當線程池中的所有任務都執行完成后,池中的所有線程都會死亡;另外也可以調用線程池的shutdownNow()方法來關閉線程池,該方法試圖停止所有正在執行的活動任務,暫停處理正在等待的任務,并返回等待的任務列表

使用線程池執行線程任務的步驟如下:

調用Executor類的靜態工廠方法創建一個ExecutorService對象,該對象代表一個線程池

創建Runnable或Callable接口實現類的實例,作為線程執行任務

調用ExcutorService的submit方法來提交Runnable或Callable實例

當不想提交任何任務時調用ExcutorService的shutdown()方法來關閉線程池

import java.util.concurrent.*;

public class ThreadPoolTest
{
    public static void main(String[] args)
        throws Exception
    {
        // 創建足夠的線程來支持4個CPU并行的線程池
        // 創建一個具有固定線程數(6)的線程池
        ExecutorService pool = Executors.newFixedThreadPool(6);
        // 使用Lambda表達式創建Runnable對象
        Runnable target = () -> {
            for (int i = 0; i < 100 ; i++ )
            {
                System.out.println(Thread.currentThread().getName() + "的i值為:" + i);
            }
        };
        // 向線程池中提交兩個線程
        pool.submit(target);
        pool.submit(target);
        // 關閉線程池
        pool.shutdown();
    }
}
Java8增強的ForkJoinPool

Java7提供了ForkJoinPool支持將一個任務拆分成多個“小任務”并行計算,再把多個“小任務”的結果合并成總的計算結果。ForkJoinPool是ExecutorService的實現類,是一種特殊的線程池

ForkJoinService提供了如下兩個常用的構造器:

ForkJoinPool(int parallelism):創建一個包含parallelism個并行線程的ForkJoinPool

ForkJoinPool():以Runtime.availableProcessors()方法的返回值作為parallelism參數來創建ForkJoinPool

Jav增加通用池功能,由如下兩個靜態方法提供通用池功能:

ForkJoinPoll commonPool():該方法返回一個通用池,通用池的運行狀態不受shutDown()或shutdownNow()方法的影響。但如果程序直接調用System.exit(0);來終止虛擬機,通用池以及通用池中正在執行的任務都會被自動終止

int getCommonPollParallelism():該方法返回通用池的并行級別

創建ForkJoinPool實例可調用ForkJoinPool的submit(ForkJoinTask task)或invoke(ForkJoinTask task)方法來執行指定任務了。其中ForkJoinTask代表一個可以并行、合并的任務

ForkJoinTask是一個抽象類,它有兩個抽象子類:RecursiveAction和RecursiveTask。其中RecursiveTask代表有返回值的任務,RecursiveAction代表沒有返回值的任務

線程池工具類的類圖:

使用RecursiveAction執行沒有返回值的“大任務”

簡單打印0~500的數值:

import java.util.concurrent.*;

// 繼承RecursiveAction來實現"可分解"的任務
class PrintTask extends RecursiveAction
{
    // 每個“小任務”只最多只打印50個數
    private static final int THRESHOLD = 50;
    private int start;
    private int end;
    // 打印從start到end的任務
    public PrintTask(int start, int end)
    {
        this.start = start;
        this.end = end;
    }
    @Override
    protected void compute()
    {
        // 當end與start之間的差小于THRESHOLD時,開始打印
        if(end - start < THRESHOLD)
        {
            for (int i = start ; i < end ; i++ )
            {
                System.out.println(Thread.currentThread().getName() + "的i值:" + i);
            }
        }
        else
        {
            // 如果當end與start之間的差大于THRESHOLD時,即要打印的數超過50個
            // 將大任務分解成兩個小任務。
            int middle = (start + end) / 2;
            PrintTask left = new PrintTask(start, middle);
            PrintTask right = new PrintTask(middle, end);
            // 并行執行兩個“小任務”
            left.fork();
            right.fork();
        }
    }
}
public class ForkJoinPoolTest
{
    public static void main(String[] args)
        throws Exception
    {
        ForkJoinPool pool = new ForkJoinPool();
        // 提交可分解的PrintTask任務
        pool.submit(new PrintTask(0 , 500));
        pool.awaitTermination(2, TimeUnit.SECONDS);
        // 關閉線程池
        pool.shutdown();
    }
}

程序實現了對指定打印任務的分解,分解后的任務分別調用fork()方法開始并行執行。ForkJoinPool啟動了4個線程來執行打印任務

使用RecursiveTask執行有返回值的“大任務”

對一個長度為100的數值的元素值進行累加:

import java.util.concurrent.*;
import java.util.*;

// 繼承RecursiveTask來實現"可分解"的任務
class CalTask extends RecursiveTask
{
    // 每個“小任務”只最多只累加20個數
    private static final int THRESHOLD = 20;
    private int arr[];
    private int start;
    private int end;
    // 累加從start到end的數組元素
    public CalTask(int[] arr, int start, int end)
    {
        this.arr = arr;
        this.start = start;
        this.end = end;
    }
    @Override
    protected Integer compute()
    {
        int sum = 0;
        // 當end與start之間的差小于THRESHOLD時,開始進行實際累加
        if(end - start < THRESHOLD)
        {
            for (int i = start ; i < end ; i++ )
            {
                sum += arr[i];
            }
            return sum;
        }
        else
        {
            // 如果當end與start之間的差大于THRESHOLD時,即要累加的數超過20個時
            // 將大任務分解成兩個小任務。
            int middle = (start + end) / 2;
            CalTask left = new CalTask(arr, start, middle);
            CalTask right = new CalTask(arr, middle, end);
            // 并行執行兩個“小任務”
            left.fork();
            right.fork();
            // 把兩個“小任務”累加的結果合并起來
            return left.join() + right.join();    // ①
        }
    }
}
public class Sum
{
    public static void main(String[] args)
        throws Exception
    {
        int[] arr = new int[100];
        Random rand = new Random();
        int total = 0;
        // 初始化100個數字元素
        for (int i = 0, len = arr.length; i < len ; i++ )
        {
            int tmp = rand.nextInt(20);
            // 對數組元素賦值,并將數組元素的值添加到sum總和中。
            total += (arr[i] = tmp);
        }
        System.out.println(total);
        // 創建一個通用池
        ForkJoinPool pool = ForkJoinPool.commonPool();
        // 提交可分解的CalTask任務
        Future future = pool.submit(new CalTask(arr, 0, arr.length));
        System.out.println(future.get());
        // 關閉線程池
        pool.shutdown();
    }
}

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

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

相關文章

  • Java線程

    摘要:中的線程池是運用場景最多的并發框架。才是真正的線程池。存放任務的隊列存放需要被線程池執行的線程隊列。所以線程池的所有任務完成后,它最終會收縮到的大小。飽和策略一般情況下,線程池采用的是,表示無法處理新任務時拋出異常。 Java線程池 1. 簡介 系統啟動一個新線程的成本是比較高的,因為它涉及與操作系統的交互,這個時候使用線程池可以提升性能,尤其是需要創建大量聲明周期很短暫的線程時。Ja...

    jerry 評論0 收藏0
  • 后端ing

    摘要:當活動線程核心線程非核心線程達到這個數值后,后續任務將會根據來進行拒絕策略處理。線程池工作原則當線程池中線程數量小于則創建線程,并處理請求。當線程池中的數量等于最大線程數時默默丟棄不能執行的新加任務,不報任何異常。 spring-cache使用記錄 spring-cache的使用記錄,坑點記錄以及采用的解決方案 深入分析 java 線程池的實現原理 在這篇文章中,作者有條不紊的將 ja...

    roadtogeek 評論0 收藏0
  • java 四種線程的使用

    摘要:四種線程池的使用介紹的弊端及四種線程池的使用,線程池的作用線程池作用就是限制系統中執行線程的數量。相比,提供的四種線程池的好處在于重用存在的線程,減少對象創建消亡的開銷,性能佳。延遲執行描述創建一個定長線程池,支持定時及周期性任務執行。 java 四種線程池的使用 介紹new Thread的弊端及Java四種線程池的使用 1,線程池的作用 線程池作用就是限制系統中執行線程的數量。 ...

    gggggggbong 評論0 收藏0
  • 跟著阿里p7一起學java高并發 - 第18天:玩轉java線程,這一篇就夠了

    摘要:高并發系列第篇文章。簡單的說,在使用了線程池之后,創建線程變成了從線程池中獲取一個空閑的線程,然后使用,關閉線程變成了將線程歸還到線程池。如果調用了線程池的方法,線程池會提前把核心線程都創造好,并啟動線程池允許創建的最大線程數。 java高并發系列第18篇文章。 本文主要內容 什么是線程池 線程池實現原理 線程池中常見的各種隊列 自定義線程創建的工廠 常見的飽和策略 自定義飽和策略 ...

    AdolphLWQ 評論0 收藏0
  • Java中的線程

    摘要:中的線程池運用場景非常廣泛,幾乎所有的一步或者并發執行程序都可以使用。代碼中如果執行了方法,線程池會提前創建并啟動所有核心線程。線程池最大數量線程池允許創建的線程最大數量。被稱為是可重用固定線程數的線程池。 Java中的線程池運用場景非常廣泛,幾乎所有的一步或者并發執行程序都可以使用。那么線程池有什么好處呢,以及他的實現原理是怎么樣的呢? 使用線程池的好處 在開發過程中,合理的使用線程...

    tomato 評論0 收藏0

發表評論

0條評論

ctriptech

|高級講師

TA的文章

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