自定義一個線程池

使用線程池的方式有許多種,可以使用JDK自帶的Executors類中創建線程池的方式。通過源碼可以看出都是使用new ThreadPoolExecutor來創建線程池的。

import com.google.common.collect.Lists;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.Builder;
import lombok.Data;

/**
 * @author :wangyongkang
 * @date :Created in 2019/12/17 5:28 下午
 * @description: 自定義一個線程池
 * @modified By:
 * @version:
 */
public class CustomThreadPool {

  /**
   * corePoolSize:核心線程數,即時是空閒的也不會被回收,除非設置allowCoreThreadTimeOut=true纔會被回收。
   * maximumPoolSize:最大線程數。
   * keepAliveTime:超過核心線程的其它線程的存活時間。
   * unit:超過核心線程的其它線程的存活時間單位。
   * workQueue:當任務塞滿了所有的線程,任務會被存放在queue中。
   * threadFactory:創建新線程使用的Factory。
   * handler:當任務數量達到了(maxPoolSize+queue)的數量,其它的任務不會處理,會調用rejectedExecution()方法。
   */
  private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,
      4,
      10,
      TimeUnit.SECONDS,
      new LinkedBlockingDeque<>(2),
      new MyThreadPoolFactory(),
      new MyRejectedExecutionHandler());

  public static void main(String[] args) {
    new CustomThreadPool().submitMethod();
  }

  /**
   * 整個執行流程
   * 1、一開始線程池中沒有線程。
   * 2、有任務進來,便會啓動core pool size。
   * 3、當超過core pool size,便會將任務放到queue中。
   * 4、當超過core pool size + queue,啓動max pool size來處理任務。
   * 5、當超過core pool size + queue,啓動(max pool size)-(core pool size)來處理任務。
   * 6、當超過max pool size + queue,調用rejectedExecution()方法。
   * 7、所有任務處理完成,(max pool size)-(core pool size)會被回收。
   * <p>
   * 注意: 如果BlockingDeque的Capacity沒有設置大小。則只會使用core pool size去處理任務。
   */
  public void submitMethod() {
    System.out.println("threads pool size:" + threadPoolExecutor.getPoolSize());
    //任務List<MyTask>
    List<MyTask> myTaskList = Lists.newArrayList();
    //任務結果List<Future<MyTask>>,返回線程的一些信息
    List<Future<MyTask>> futureList = Lists.newArrayList();
    int i = 0;
    while (i < 10) {
      myTaskList.add(MyTask.builder().name("task" + (i++)).build());
    }
    myTaskList.forEach(o -> {
      futureList.add(threadPoolExecutor.submit(o));
    });
    System.out.println("threads pool size:" + threadPoolExecutor.getPoolSize());
    System.out.println("futureList-->:" + futureList);
    try {
      Thread.sleep(20000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("threads pool size:" + threadPoolExecutor.getPoolSize());
  }
}

/**
 * 自定義ThreadPoolFactory
 * 抄一下Executors是怎麼寫的
 */
class MyThreadPoolFactory implements ThreadFactory {

  private static final AtomicInteger poolNumber = new AtomicInteger(1);
  private final ThreadGroup group;
  private final AtomicInteger threadNumber = new AtomicInteger(1);
  private final String namePrefix;

  MyThreadPoolFactory() {
    SecurityManager s = System.getSecurityManager();
    group = (s != null) ? s.getThreadGroup() :
        Thread.currentThread().getThreadGroup();
    namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
  }

  @Override
  public Thread newThread(Runnable r) {
    Thread t = new Thread(group, r,
        namePrefix + threadNumber.getAndIncrement(),
        0);
    if (t.isDaemon()) {
      t.setDaemon(false);
    }
    if (t.getPriority() != Thread.NORM_PRIORITY) {
      t.setPriority(Thread.NORM_PRIORITY);
    }
    return t;
  }
}

/**
 * 自定義RejectedExecutionHandler
 * 抄一下Executors是怎麼寫的
 */
class MyRejectedExecutionHandler implements RejectedExecutionHandler {

  @Override
  public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    try {
      throw new RejectedExecutionException(
          "Task " + r.toString() + " rejected from " + e.toString());
    } catch (RejectedExecutionException re) {
      System.out.println(re.getMessage());
      re.printStackTrace();
    }
  }

}

/**
 * 自定義Callable
 */
@Data
@Builder
class MyTask implements Callable<MyTask> {

  private String name;

  @Override
  public MyTask call() {
    System.out.println("ThreadName:" + Thread.currentThread().getName() + ",taskName:" + name);
    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return this;
  }
}

 

發佈了40 篇原創文章 · 獲贊 40 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章