中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

java~線程(cheng)池的總結(jie)~續

上一講主要談了java里的線程池的使用,而主要使用Executors的方式去創建,比如 Executors.newCachedThreadPool(), Executors.newFixedThreadPool(5)等等,而這些方式在阿里手冊里是不被推薦的,而是推薦使用ThreadPoolExecutor的方式,我(wo)想(xiang)應該也是避免資(zi)源耗盡的風險(xian)吧!

線(xian)程池不允許使用 Executors 去創(chuang)建,而(er)是(shi)通過 ThreadPoolExecutor 的(de)方式(shi),這樣(yang)的(de)處理(li)方式(shi)讓寫的(de)同學更加明確(que)線(xian)程池的(de)運(yun)行規則,規避(bi)資源(yuan)耗盡的(de)風(feng)險。

ThreadPoolExecutor實現的線程池

阿(a)里巴巴的(de)JAVA開發(fa)手冊推(tui)薦(jian)用ThreadPoolExecutor創建線程池。來看看ThreadPoolExecutor創建線程池的(de)api:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) 

參數解釋

corePoolSize : 線程池核心池的大小。
maximumPoolSize : 線程池的最大線程數。
keepAliveTime : 當線程數大于核心時,此為終止前多余的空閑線程等待新任務的最長時間。
unit : keepAliveTime 的時間單位。
workQueue : 用來儲存等待執行任務的隊列。
threadFactory : 線程工廠。
handler  拒絕策略。

原理

有(you)請求(qiu)時(shi),創建(jian)線(xian)(xian)程(cheng)執(zhi)行任務,當(dang)線(xian)(xian)程(cheng)數量(liang)等于corePoolSize時(shi),請求(qiu)加入(ru)阻塞隊列里,當(dang)隊列滿了時(shi),接著創建(jian)線(xian)(xian)程(cheng),線(xian)(xian)程(cheng)數等于maximumPoolSize。 當(dang)任務處(chu)理(li)不過來的時(shi)候,線(xian)(xian)程(cheng)池開始執(zhi)行拒絕(jue)策略。

阻塞隊列

ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。
LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。
PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。
DelayQueue: 一個使用優先級隊列實現的無界阻塞隊列。
SynchronousQueue: 一個不存儲元素的阻塞隊列。
LinkedTransferQueue: 一個由鏈表結構組成的無界阻塞隊列。
LinkedBlockingDeque: 一個由鏈表結構組成的雙向阻塞隊列。

拒絕策略

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

Executors的弊端

  1. newFixedThreadPool 和 newSingleThreadExecutor:主要問題是堆積的請求處理隊列可能會耗費非常大的內存,甚至 OOM。
  2. newCachedThreadPool 和 newScheduledThreadPool:主要問題是線程數最大數是 Integer.MAX_VALUE,可能會創建數量非常多的線程,甚至 OOM。

合理配置線程池大小

根據任務所需要的cpu和(he)io資源的量可以分為:

  1. CPU密集型任務: 主要是執行計算任務,響應時間很快,cpu一直在運行,這種任務cpu的利用率很高。
  2. IO密集型任務:主要是進行IO操作,執行IO操作的時間較長,這是cpu出于空閑狀態,導致cpu的利用率不高。

為了合理最大限度的(de)使用(yong)系統資(zi)源同時(shi)也要保證的(de)程序的(de)高性能,可以(yi)給CPU密集型任(ren)(ren)務(wu)和IO密集型任(ren)(ren)務(wu)配置一些(xie)線程數。

  1. CPU密集型:線程個數為CPU核數。這幾個線程可以并行執行,不存在線程切換到開銷,提高了cpu的利用率的同時也減少了切換線程導致的性能損耗
  2. IO密集型:線程個數為CPU核數的兩倍。到其中的線程在IO操作的時候,其他線程可以繼續用cpu,提高了cpu的利用率。

什么時候會走拒絕策略

如果(guo)你有10個線程(cheng),而線程(cheng)池的配置是maximumPoolSize=4,ArrayBlockingQueue.length=3,corePoolSize=3,那么當(dang)你的線程(cheng)產(chan)生的數量大于maximumPoolSize+ArrayBlockingQueue.length,即(ji)大于4+3時,就(jiu)會走拒絕策略。

@SneakyThrows
@Test
public void threadPoolExecutor() {
    RejectedExecutionHandler handler = new MyIgnorePolicy();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),
            handler);
    for (int i = 1; i <= 5; i++) {
        MyTask task = new MyTask(String.valueOf(i));
        executor.execute(task);
    }

    System.in.read(); //阻塞主線程
}
public static class MyIgnorePolicy implements RejectedExecutionHandler {

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        doLog(r, e);
    }

    private void doLog(Runnable r, ThreadPoolExecutor e) {
        // 可做日志記錄等
        System.err.println(r.toString() + " rejected");
    }
}

static class MyTask implements Runnable {
    private String name;

    public MyTask(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.println(this.toString() + " is running!");
            Thread.sleep(3000); //讓任務執行慢點
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "MyTask [name=" + name + "]";
    }
}

結果,將有7個被執行,3個被拒絕

總結:線程池中核心數只影響任務處理的速度,而是否會走拒絕策略是由最大線程數和隊列長度決定的。

posted @ 2020-03-29 12:16  張占嶺  閱讀(481)  評論(0)    收藏  舉報