亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

如何進行ScheduledThreadPoolExecutor分析與線程池防坑

發布時間:2021-12-17 14:36:11 來源:億速云 閱讀:244 作者:柒染 欄目:大數據

這篇文章給大家介紹如何進行ScheduledThreadPoolExecutor分析與線程池防坑,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

Java線程池使用不當會導致很多線上問題,常見的有:

  • 線程池默認使用無界隊列,任務過多時,JVM OOM

  • 不設置最大線程數,線程數目暴漲

  • 定時執行,執行一次任務耗時太長甚至一直阻塞,達不到定時執行的目的

  • 線程池內的線程是非守護線程,停止JVM時出問題

  • 使用submit方法,沒有調用future.get()導致異常被吞,execute不會有異常被吞的問題

  • 死鎖問題,并不常見,但是有時候寫復雜了可能會出現。一句話,使用線程池和諸如阻塞隊列這種抽象層次比較高的工具時,盡量不要再用低層次的類,如lock,wait(),notify()等,這樣混用會導致難以排查的問題。

ScheduledExecutorService分析

	ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(4);
        scheduledService.scheduleAtFixedRate(() -> {
            try {
                System.out.println("pool thread:" + Thread.currentThread().isDaemon());
                System.out.println("start at:" + new Date());
                Thread.sleep(10000);
                System.out.println("end at:" + new Date());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, 0, 5, TimeUnit.SECONDS);

上面的代碼塊意圖每5秒執行一次任務,但是執行這個任務需要耗費10秒(sleep),那么肯定不能達到5秒一次的效果。分析一下原因。
定時執行功能的實現類是ScheduledThreadPoolExecutor,它是一個線程池加延遲隊列來實現的,延遲隊列是使用堆來實現的,也就是根元素值最大或者值最小,在定時任務執行這個場景下,根元素就是下一個要執行的任務,然后有一個等待時間。

	public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit) {
        if (command == null || unit == null)
            throw new NullPointerException();
        if (period <= 0)
            throw new IllegalArgumentException();
        ScheduledFutureTask<Void> sft =
            new ScheduledFutureTask<Void>(command,
                                          null,
                                          triggerTime(initialDelay, unit),
                                          unit.toNanos(period));
        RunnableScheduledFuture<Void> t = decorateTask(command, sft);
        sft.outerTask = t;
        delayedExecute(t);
        return t;
    }

然后看ScheduledFutureTask這個類的run()方法

	public void run() {
            boolean periodic = isPeriodic();//是否周期執行
            if (!canRunInCurrentRunState(periodic))
                cancel(false);
            else if (!periodic)
                ScheduledFutureTask.super.run();//不是執行一次就完了
            else if (ScheduledFutureTask.super.runAndReset()) {//執行
                setNextRunTime();//設置下次時間
                reExecutePeriodic(outerTask);//加入隊列
            }
        }
void reExecutePeriodic(RunnableScheduledFuture<?> task) {
        if (canRunInCurrentRunState(true)) {
            super.getQueue().add(task);
            if (!canRunInCurrentRunState(true) && remove(task))
                task.cancel(false);
            else
                ensurePrestart();//決定線程池是否新增線程,未達到核心線程數,有新任務則加線程
        }
    }

可以看到如果一次執行時間很長,是達不到定時執行的目的,最終的表現就是一次連著一次執行,如果我們確實需要精準的定期執行,不關注每次多長時間,該怎么辦?很簡單,再弄一個線程池專門用來干活

關于如何進行ScheduledThreadPoolExecutor分析與線程池防坑就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

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

AI

双辽市| 乌拉特后旗| 宜昌市| 天峻县| 肇庆市| 离岛区| 外汇| 剑河县| 泾阳县| 绥德县| 大名县| 鄂尔多斯市| 阳信县| 肥东县| 巴林右旗| 九台市| 前郭尔| 陆良县| 新乡县| 方正县| 长宁县| 新巴尔虎左旗| 滕州市| 武邑县| 九寨沟县| 洛阳市| 马山县| 九龙县| 手游| 治县。| 肇庆市| 襄城县| 昌宁县| 中西区| 延长县| 青神县| 彭山县| 德安县| 肥城市| 肥西县| 景洪市|