自己动手写线程池

Posted jiangwangxiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己动手写线程池相关的知识,希望对你有一定的参考价值。

一、线程池源码如下

1、阻塞任务队列 BlockingQueue

public interface BlockingQueue<E> {
  boolean offer(E e);
  public E take();
}

阻塞任务队列实现类  LinkedBlockingQueue

import java.util.concurrent.atomic.AtomicInteger;

public class LinkedBlockingQueue<E> implements BlockingQueue<E> {
  private final AtomicInteger count = new AtomicInteger();
  private final int capacity;

  transient Node<E> head;
  private transient Node<E> last;

  public LinkedBlockingQueue(int capacity) {
    this.capacity = capacity;
    last = head = new Node<E>(null);
  }
  //向阻塞队列的尾部添加一个任务
  @Override
  public boolean offer(E e) {
    //如果已达到队列的容量,则拒接添加,返回false
    if(count.get() == capacity) {
      return false;
    }
    Node<E> node = new Node<E>(e);
    last = last.next = node;
    count.getAndIncrement();
    return true;
  }

  //从阻塞队列的头部取出一个任务
  @Override
  public E take() {
    Node<E> h = head.next;
    if(h == null) {
      return null;
    }
    E x = h.item;
    head = h;
    return x;
  }

  static class Node<E>{
    E item;
    Node<E> next;

    Node(E x){
      item = x;
    }
  }
}

2、创建线程的工厂  ThreadFactory

public interface ThreadFactory {
  Thread newThread(Runnable r);
}

创建线程的工厂实现类    MyThreadFactory

import java.util.concurrent.atomic.AtomicInteger;

public class MyThreadFactory implements ThreadFactory {
  private final AtomicInteger threadNumber = new AtomicInteger(1);

  @Override
  public Thread newThread(Runnable r) {
    Thread t = new Thread(r, "demo" + threadNumber.getAndIncrement());
    return t;
  }
}

3、线程池接口   ExecutorService

public interface ExecutorService {
  void execute(Runnable command);
}

线程池实现类    ThreadPoolExecutor

import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolExecutor implements ExecutorService{
  private final HashSet<Worker> workers = new HashSet<Worker>();
  private static final AtomicInteger ctl = new AtomicInteger(0);

  private final BlockingQueue<Runnable> workQueue;
  private volatile ThreadFactory threadFactory;
  private volatile int corePoolSize;
  private volatile int maximumPoolSize;

  public ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               BlockingQueue<Runnable> workQueue,
              ThreadFactory threadFactory) {
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.threadFactory = threadFactory;
  }

  @Override
  public void execute(Runnable command) {
    //如果线程池当前线程数小于核心线程数,则调用addWorker方法增加一个工作线程
    if(ctl.get() < corePoolSize) {
      if(addWorker(command, true)) {
        return;
      }
    }
    //否则尝试将该任务添加到任务队列
    if(workQueue.offer(command)) {
      workQueue.offer(command);
    }else{//如果添加该任务到任务队列失败则说明任务队列已满,新开启线程执行该任务
      //如果新开启线程失败
      if(!addWorker(command, false)) {
        System.out.println("任务" + command + "被线程池拒绝");
      }
    }
  }

  private boolean addWorker(Runnable firstTask, boolean core) {
    int c = ctl.get();
    if(c >= (core ? corePoolSize : maximumPoolSize)) {
      return false;
    }
    ctl.compareAndSet(c, c+1);

    Worker w = new Worker(firstTask);
    final Thread t = w.thread;
    workers.add(w);
    t.start();

    return true;
  }

  private final class Worker implements Runnable{
    final Thread thread;
    Runnable firstTask;

    Worker(Runnable firstTask) {
      this.firstTask = firstTask;
      this.thread = threadFactory.newThread(this);
    }

    @Override
    public void run() {
      Runnable task = this.firstTask;
      while (task != null || (task = workQueue.take()) != null) {
        task.run();
        task = null;
      }
    }
  }
}

4、创建线程池的工具类   Executors

public class Executors {
  public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads, new LinkedBlockingQueue<Runnable>(2), new MyThreadFactory());
  }
}

 

二、测试线程池的功能

public class ThreadTest {
  public static void main(String[] args) {
    /**
    * 1、使用Executors创建线程池
    */
    // ExecutorService executors = Executors.newFixedThreadPool(2);
    /**
    * 2、直接new ThreadPoolExecutor,并指定corePoolSize和maximumPoolSize不一样
    */
    ExecutorService executors = new ThreadPoolExecutor(2, 4,
          new LinkedBlockingQueue<Runnable>(3), new MyThreadFactory());

    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 111");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 222");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 333");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 444");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 555");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 666");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 777");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    executors.execute(new Runnable() {
      @Override
      public void run() {
        int i = 0;
        while(i++ < 5) {
          System.out.println(Thread.currentThread().getName() + "-- 888");
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });

    System.out.println("主函数结束");
  }
}

 

从输出结果可以看出,启动了4个线程,并且有线程执行了多个任务,有任务被拒绝





































































































































































































































































以上是关于自己动手写线程池的主要内容,如果未能解决你的问题,请参考以下文章

死磕 java线程系列之自己动手写一个线程池(续)

死磕 java线程系列之自己动手写一个线程池(续)

自己动手写线程池

想深入了解线程池底层原理?那就动手写一个吧!

自己动手写把”锁”之---锁的作用

自己动手写区块链之交易中继