自己动手写线程池——向JDK线程池进发( 三 )


  /**   *   * @param runnable 需要被执行的任务   * @param max 是否使用 maximumPoolSize   * @return boolean   */  public synchronized boolean addWorker(Runnable runnable, boolean max) {    if (ct.get() >= corePoolSize && !max)      return false;    if (ct.get() >= maximumPoolSize && max)      return false;    Worker worker = new Worker(runnable);    workers.add(worker);    Thread thread = new Thread(worker, "ThreadPool-" + "Thread-" + ct.addAndGet(1));    thread.start();    return true;  }实现Callable这个函数其实比较简单,只需要将传入的Callable对象封装成一个FutureTask对象即可,因为FutureTask实现了Callable和Runnable两个接口,然后将这个结果返回即可,得到这个对象,再调用对象的 get 方法就能够得到结果 。
  public <V> RunnableFuture<V> submit(Callable<V> task) throws InterruptedException {    checkPoolState();    FutureTask<V> futureTask = new FutureTask<>(task);    execute(futureTask);    return futureTask;  }拒绝策略的实现根据前面提到的各种策略的具体实现方式,具体的代码实现如下所示:
  private void reject(Runnable runnable) throws InterruptedException {    switch (policy) {      case ABORT:        throw new RuntimeException("task queue is full");      case CALLER_RUN:        runnable.run();      case DISCARD: // 直接放弃这个任务        return;      case DISCARD_OLDEST:        // 放弃等待时间最长的任务 也就是队列当中的第一个任务        taskQueue.poll();        execute(runnable); // 重新执行这个任务    }  }线程池关闭实现一共两种方式实现线程池关闭:

  • 直接关闭线程池,不管任务队列当中的任务是否被全部执行完成 。
  • 安全关闭线程池,先等待任务队列当中所有的任务被执行完成,再关闭线程池,但是在这个过程当中不允许继续提交任务了,这一点已经在函数 checkPoolState 当中实现了 。
  // 强制关闭线程池  public synchronized void stop() {    isStopped = true;    for (Worker worker : workers) {      worker.stopWorker();    }  }  public synchronized void shutDown() {    // 先表示关闭线程池 线程就不能再向线程池提交任务    isStopped = true;    // 先等待所有的任务执行完成再关闭线程池    waitForAllTasks();    stop();  }  private void waitForAllTasks() {    // 当线程池当中还有任务的时候 就不退出循环    while (taskQueue.size() > 0) {      Thread.yield();      try {        Thread.sleep(1000);      } catch (InterruptedException e) {        e.printStackTrace();      }    }  }

经验总结扩展阅读