Java线程池的实现原理(含示例代码)

线程是一个独立的程序执行路径,线程池是一组执行任务的线程,在java中每个线程都继承java.lang.Thread,或实现java.lang.Runnable。

JAVA线程池

线程池是一组执行任务的工作线程,每个线程可以多次重用,如果所有线程都处于活动状态时,新加入的任务,会被加入等待队列,直到有线程可用。线程池内部所采用的队列,通常为LinkedBlockingQueue,用于向队列添加和删除任务。

通常我们需要的是有固定线程数量的线程池,与wait()结合,新任务到达时利用notify()通知,以下示例是一个简单的,基于工作队列的线程池,队列中存放着Runnable对象 (任务执行单元)。这是调度程序和工作队列的常见做法,尽管Thread API没有特别指出应采用Runnable接口。

JAVA线程池示意代码

package com.xieyonghui.art;

import java.util.concurrent.LinkedBlockingQueue;

public class ThreadPool {

  public static void main(String... strings) {
    ThreadPool threadPool = new ThreadPool(10);
    for (int i = 0; i < 10; i++) {
      // Task t = new Task();
      // 因为创建内部类对象需要已知外部类对象,
      // 在此就不用threadPool.new Task()的方式;直接用lambda的写法
      threadPool.execute(() -> {
        System.out.println("business");
      });
    }
  }

  /**
   * 线程池的基本结构
   */

  // 线程数量
  private int tpc = 5;
  // (线程)执行单元
  private final Worker[] worker;
  // 任务队列
  private final LinkedBlockingQueue<Runnable> queue;

  // 构造线程池
  public ThreadPool(int thread) {
    queue = new LinkedBlockingQueue();
    worker = new Worker[thread];
    tpc = thread;

    for (int i = 0; i < tpc; i++) {
      worker[i] = new Worker();
      // 启动所有线程并处于等待状态
      worker[i].start();
    }

  }

  // 加入新的任务
  public void execute(Runnable task) {
    synchronized (queue) {
      // 把任务加入队列
      queue.add(task);
      // 然后通知在队列上等待的线程
      queue.notify();
    }
  }

  // 任务执行单元
  class Worker extends Thread {

    @Override
    public void run() {
      Runnable t;
      while (true) {
        synchronized (queue) {
          while (queue.isEmpty()) {
            try {
              // 队列任务为空,则wait
              queue.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          // 被唤醒后从队列中取出一个任务
          t = queue.poll();
        }
        try {
          // 执行任务
          t.run();
        } catch (Throwable ex) {
          ex.printStackTrace();
        }
      }
    }

  }

  // 业务逻辑处理单元
  class Task implements Runnable {
    @Override
    public void run() {
      System.out.println("business");
    }

  }

}