91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

Java實現終止線程池中正在運行的定時任務

發布時間:2020-10-06 04:43:24 來源:腳本之家 閱讀:182 作者:laozhang 欄目:編程語言

最近項目中遇到了一個新的需求,就是實現一個可以動態添加定時任務的功能。說到這里,有人可能會說簡單啊,使用quartz就好了,簡單粗暴。然而quartz框架太重了,小項目根本不好操作啊。當然,也有人會說,jdk提供了timer的接口啊,完全夠用啊。但是我們項目的需求完全是多線程的模型啊,而timer是單線程的,so,樓主最后還是選擇了jdk的線程池。

線程池是什么

Java通過Executors提供四種線程池,分別為:
newCachedThreadPool :創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
newFixedThreadPool : 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
newScheduledThreadPool : 創建一個定長線程池,支持定時及周期性任務執行。
newSingleThreadExecutor : 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

樓主項目中用到的是newScheduledThreadPool, 就這些吧,再多的樓主就班門弄斧了,Google一下,一大堆。

線程池service的獲取

樓主通過單例模式來獲取線程池的service,代碼如下:

/**
 * 線程池創建.
 * @author wuhf
 * @date 2018/01/16
 */
public class ThreadPoolUtils {

  private static ScheduledExecutorService executorService;

  private ThreadPoolUtils() {
    //手動創建線程池.
    executorService = new ScheduledThreadPoolExecutor(10,
        new BasicThreadFactory.Builder().namingPattern("syncdata-schedule-pool-%d").daemon(true).build());
  }

  private static class PluginConfigHolder {
    private final static ThreadPoolUtils INSTANCE = new ThreadPoolUtils();
  }

  public static ThreadPoolUtils getInstance() {
    return PluginConfigHolder.INSTANCE;
  }

  public ScheduledExecutorService getThreadPool(){
    return executorService;
  }

}

中斷某一個正在運行的線程代碼實現

廢話就不多說了,代碼如下:

/**
 * 中斷線程池的某個任務.
 */
public class InterruptThread implements Runnable {

  private int num;

  public InterruptThread (int num){
    this.num = num;
  }

  public static void main(String[] args) throws InterruptedException {

    Thread interruptThread = new Thread(new InterruptThread(1));
    ScheduledFuture<?> t = ThreadPoolUtils.getInstance().getThreadPool().scheduleAtFixedRate(interruptThread,0,2,
        TimeUnit.SECONDS);

    InterruptThread interruptThread1 = new InterruptThread(2);
    ThreadPoolUtils.getInstance().getThreadPool().scheduleAtFixedRate(interruptThread1,0,2,
        TimeUnit.SECONDS);

    InterruptThread interruptThread2 = new InterruptThread(3);
    ThreadPoolUtils.getInstance().getThreadPool().scheduleAtFixedRate(interruptThread2,0,2,
        TimeUnit.SECONDS);
    Thread.sleep(5000);

		//終止正在運行的線程interruptThread
    t.cancel(true);
    while (true){

    }
  }

  @Override
  public void run() {
    System.out.println("this is a thread" + num);
  }
}

踩坑記錄

樓主在使用如下代碼時,突然想到當這個定時任務需要被停止時該如何停止線程運行

ThreadPoolUtils.getInstance().getThreadPool().scheduleAtFixedRate(interruptThread,0,2,
        TimeUnit.SECONDS);

既然我有這樣的需求,那就Google一下吧,找了大半圈,愣是沒找到相關資料,都是一些關于Java線程池的深入分析。或者是全局變量啥的,并沒有找到令樓主滿意的解決方案。

既然沒有線程的那就扒一下scheduleAtFixedRate的底層源碼看看是什么東西吧,果不其然我在源碼中看到了scheduleAtFixedRate方法的具體實現,發現他的返回值是ScheduledFuture。

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;
  }

接著往下我們再看看ScheduledFuture里面有什么東西吧,沒有讓樓主失望,看到了這個

public boolean cancel(boolean mayInterruptIfRunning) {
      boolean cancelled = super.cancel(mayInterruptIfRunning);
      if (cancelled && removeOnCancel && heapIndex >= 0)
        remove(this);
      return cancelled;
}
      
//從線程的運行隊列中移除當前線程
public boolean remove(Runnable task) {
    boolean removed = workQueue.remove(task);
    tryTerminate(); // In case SHUTDOWN and now empty
    return removed;
}

再往上查super.cancel(mayInterruptIfRunning)是什么東西,我們看到了這個,

//通過調用線程的interrupt方法終止線程運行
public boolean cancel(boolean mayInterruptIfRunning) {
    if (!(state == NEW &&
       UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
         mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
      return false;
    try {  // in case call to interrupt throws exception
      if (mayInterruptIfRunning) {
        try {
          Thread t = runner;
          if (t != null)
            t.interrupt();
        } finally { // final state
          UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
        }
      }
    } finally {
      finishCompletion();
    }
    return true;
  }

到這里所有的問題都迎刃而解。

總結一下吧

項目中總是會遇到比較難搞的解決方案,當Google不太好找時,翻一下jdk的源碼或許也是一個不錯的方法。

向AI問一下細節

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

AI

微博| 博乐市| 玛纳斯县| 策勒县| 湘西| 烟台市| 惠来县| 葫芦岛市| 剑阁县| 淮安市| 太原市| 长寿区| 当涂县| 双柏县| 井陉县| 新竹市| 塔城市| 霸州市| 东乡| 海兴县| 泾源县| 锡林浩特市| 郴州市| 成都市| 新田县| 吉林省| 孟连| 湘阴县| 依兰县| 琼中| 甘谷县| 临桂县| 满洲里市| 沙湾县| 雷州市| 桐城市| 巴楚县| 揭东县| 大姚县| 霍州市| 万安县|