加入收藏 | 设为首页 | 会员中心 | 我要投稿 财气旺网 - 财气网 (https://www.caiqiwang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

什么是线 程池

发布时间:2023-02-03 10:55:22 所属栏目:Linux 来源:
导读:  线程池从功能上来看,就是一个任务管理器。在Java中,Executor接口是线程池的根接口,其中只包含一个方法。

  Executor

  void execute(Runnable command); // 执行任务
  ExecutorService继承了
  线程池从功能上来看,就是一个任务管理器。在Java中,Executor接口是线程池的根接口,其中只包含一个方法。
 
  Executor
 
  void execute(Runnable command);  // 执行任务
  ExecutorService继承了Executor接口,提供了一些线程池的基础方法:
 
  void shutdown();      // 关闭线程池(不接受新任务,但是旧任务会执行)
    List<Runnable> shutdownNow();     // 关闭线程池,返回待执行任务
    boolean isShutdown();     // 线程池是否会关闭
    boolean isTerminated();   // 关闭之前所有任务是否被关闭。(必须先执行过shutdown)
    ....
  再往下是两种线程池的实现:ThreadPoolExecutor和ForkJoinPool。ThreadPoolExecutor中维护了一个BlockingQueue阻塞队列保存所有的待执行任务,而ForkJoinPool中每一个线程都有自己的BlockingQueue用来存储任务。
 
  ThreadPoolExecutor
 
  在ThreadPoolExecutor的构造方法中,需要提供几个参数:corePoolSize、maximumPoolSize、keepAliveTime、BlockingQueue、RejectedExecutionHandler。其中corePoolSize表示当前线程池维护几个线程,maximumPoolSize表示允许的最大线程数。keepAliveTime表示如果当前线程数在 corePoolSize和maximumPoolSize之间时,允许在多久时间内保持存活等待新任务。BlockingQueue是保存任务的阻塞队列,RejectedExecutionHandler是不同的拒绝策略。
 
  public ThreadPoolExecutor(int corePoolSize,
                                int maximumPoolSize,
                                long keepAliveTime,
                                TimeUnit unit,
                                BlockingQueue<Runnable> workQueue,
                                RejectedExecutionHandler handler) {
          this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
               Executors.defaultThreadFactory(), handler);
      }
 
  那么ThreadPoolExecutor中是如何创建新线程呢?
 
  在接到请求执行一个新任务时,首先会判断当前线程数是否大于corePoolSize,如果没有则创建新线程。否则将当前任务放到阻塞队列中,如果当前队列已满,则创建新的线程执行任务。在成功将当前任务放到队列中之后,我们还需要二次判断当前线程池中是否有线程已经销毁或者当前线程池停止运行。当线程数量大于maximumPoolSize时,执行拒绝策略。
 
  这段代码在ThreadPoolExecutor的excute方法中体现线程池linux,其中也有详细地对执行任务顺序的描述。
 
  public void execute(Runnable command) {
          if (command == null)
              throw new NullPointerException();
          /*
           * Proceed in 3 steps:
           *
           * 1. If fewer than corePoolSize threads are running, try to
           * start a new thread with the given command as its first
           * task.  The call to addWorker atomically checks runState and
           * workerCount, and so prevents false alarms that would add
           * threads when it shouldn't, by returning false.
           *
           * 2. If a task can be successfully queued, then we still need
           * to double-check whether we should have added a thread
           * (because existing ones died since last checking) or that
           * the pool shut down since entry into this method. So we
           * recheck state and if necessary roll back the enqueuing if
           * stopped, or start a new thread if there are none.
 
           *
           * 3. If we cannot queue task, then we try to add a new
           * thread.  If it fails, we know we are shut down or saturated
           * and so reject the task.
           */
          int c = ctl.get();
          if (workerCountOf(c) < corePoolSize) {
              if (addWorker(command, true))
                  return;
              c = ctl.get();
          }
          if (isRunning(c) && workQueue.offer(command)) {
              int recheck = ctl.get();
              if (! isRunning(recheck) && remove(command))
                  reject(command);
              else if (workerCountOf(recheck) == 0)
                  addWorker(null, false);
          }
          else if (!addWorker(command, false))
              reject(command);
      }
  如何设置线程池的线程数量:如果是CPU密集型应用,则线程大小为N或者N+1;如果是IO密集型应用,则线程大小为2N或者2N+2.

(编辑:财气旺网 - 财气网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!