Java常用类:ThreadPoolExecutor线程池

作为一个稀有的Java妹子,所写的所有博客都只是当作自己的笔记,留下证据自己之前是有用心学习的~哈哈哈哈(如果有不对的地方,也请大家指出,不要悄悄咪咪的不告诉我)

为什么需要线程池

首先举例一个业务场景,也是日常开发中经常会遇到的场景,手机短信验证业务。
短信验证在很多业务场景中都会遇到,比如验证码登录,短信提示余额不足等等。类似这种不影响主线程业务的,在访问量很大的情况下,就需要考虑使用多线程开发,避免访问量大时,造成接口阻塞。

那么有人会问了,既然需要多线程开发,那么在代码里直接创建线程来处理就好了呀。这种显示的在代码里创建线程的方式是不可取的,因为如果频繁的创建销毁线程,或者线程数太多,内存切换线程耗时久会造成服务器卡死。

所以,在不阻塞主线程的情况,使用另外的线程来处理某些业务时,就需要使用多线程,又因为频繁创建销毁线程十分耗时,线程池就应运而生啦。

线程池是什么

从字面上理解,就是装有线程的池子,这些线程可以处理特殊的业务,池子里有存放任务的队列,当队列里有任务时,线程会去队列里取任务执行,当队列为空时,线程就会等待。

结合业务场景分析,当需要发送短信时,就调用线程池,线程池会把发送短信的任务放到队列中(不准确,后面会细说,不是直接放队列),线程就会去队列中拿任务,执行发送短信,那么主线程就只管把发送短信的任务往线程池的队列中放,然后继续执行其他的逻辑。

贴一段生产环境的部分业务代码,支付订单成功后,在回调里处理跨境商品报关,当有很多用户支付成功时,这个方法就会被频繁调用,跨境商品报关就可以使用线程池来处理,这样接口的响应就会很快,因为不用等待短信处理的结果。

  /**
   * 完成支付 回调
   */
  public boolean compeletPay(PayOrderRes res) {
 	  // 销售单和收款单 推送金蝶
      k3OrderSellSender.send(order.getTransactionNo());
      //添加报关记录
      transCustomsService.addTransCustomsRecord(order.getTransactionNo());
      //跨境商品报关
      customsDeclareLogic
          .synchCustomsDeclare(order.getTransactionNo(), String.valueOf(order.getUserId()), 2);
}

源码解析

1.继承关系

ThreadPoolExecutor extends AbstractExecutorService
AbstractExecutorService implements ExecutorService
ExecutorService extends Executor

Executor是线程池的顶级接口,只有一个execute方法

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

ExecutorService继承了Executor,新增了许多方法

public interface ExecutorService extends Executor {
	void shutdown();
	List<Runnable> shutdownNow();
	boolean isShutdown();
	boolean isTerminated();
	<T> Future<T> submit(Callable<T> task);
}

2.成员变量

/**
线程池的状态
*/
//调用execute方法后,线程池就进行运行状态
private static final int RUNNING    = -1 << COUNT_BITS;
//调用shutdown方法后,线程就不再接收新的任务,正在执行的任务会执行完毕再真正关闭线程池
private static final int SHUTDOWN   =  0 << COUNT_BITS;
//调用shutdownNow方法后,线程不再接收新的任务,并且尝试关闭正在执行的线程
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
//当线程为shutdown/stop,且线程全部销毁后,线程池的状态就是终止
private static final int TERMINATED =  3 << COUNT_BITS;
/**
存放任务的队列
*/
private final BlockingQueue<Runnable> workQueue;
/**
存放线程的集合
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
创建线程的工厂
*/
private volatile ThreadFactory threadFactory;
/**
队列里的任务满了时,拒绝处理的handler
*/
private volatile RejectedExecutionHandler handler;
/**
当前线程池中的线程数
*/
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
/**
线程池核心大小,线程里可以有多少线程
*/
private volatile int corePoolSize;
/**
线程池最大线程数
*/
private volatile int maximumPoolSize;
/**
线程保持活跃的时间,当超过核心线程数,就会创建新的线程,这部分线程当不处理任务时,就会判断是否超过活跃时间,超过即销毁
*/
private volatile long keepAliveTime;

3.构造方法

//一共有四个
 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
     public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

构造方法初始化:核心线程数,最大线程数,活跃时间,时间单元,队列,线程工厂,拒绝处理handler

4.execute方法

//参数是线程,调用该方法就可以把线程放入线程池中,然后执行业务代码
public void execute(Runnable command) {
		//判断传进来的线程是否为空,是的话就抛出异常
        if (command == null)
            throw new NullPointerException();
        //获取当前线程池的线程数量
        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);
    }

//当线程池中的线程数<核心线程数时,创建worker,即线程
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        //比较线程池的数量与核心线程数量,判断线程池队列是否为空,线程池的状态是否为RUNNING等等
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
			
            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                 //将线程池中的线程数+1
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
		
		//当通过检验后,创建线程
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
        	//使用worker创建线程,Worker是ThreadPoolExecutor的内部类,专门用来创建线程,管理线程的
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());
					//拿到锁后再次判断线程池的状态
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        //添加线程
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                	//启动线程,注意这里的start会运行Worker里的Run方法,后面有介绍
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

//内部类Worker
private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        private static final long serialVersionUID = 6138294804551838833L;
        final Thread thread;
        Runnable firstTask;
        volatile long completedTasks;
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }
        
        public void run() {
        	//看下这个方法
            runWorker(this);
        }
    }

final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        //这个task就是调用execute时传入的线程,这个线程里的run方法里才是业务逻辑代码
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
        	//判断队列是否为空,不为空则从队列中获取任务
            while (task != null || (task = getTask()) != null) {
                w.lock();
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                    	//运行业务线程
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }
//从队列获取任务
private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
            	//获取任务
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

5.其他方法

1.shutdown()

public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }
private void checkShutdownAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(shutdownPerm);
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            } finally {
                mainLock.unlock();
            }
        }
    }
private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

6.Executor和Executors的区别

Executor是线程池的顶级接口,Executors提供了一些创建线程池的方法

public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
    ......
}

举例

我直接贴生产环境的业务代码出来,look look

public class CustomsDeclareLogic {
  @Autowired
  EpayService epayService;
  @Autowired
  AlipayService alipayService;
  @Autowired
  WxPayService wxPayService;


  public class CustomsDeclareThread implements Runnable {

    private String transactionNo;
    private String userId;
    /**
    * 1新增报关记录,2修改报关记录
    */
    private Integer action;

    public CustomsDeclareThread(String transactionNo, String userId, Integer action) {
      this.transactionNo = transactionNo;
      this.userId = userId;
      this.action = action;
    }

    @Override
    public void run() {
      try {
      	//处理业务逻辑
        declareOrder(transactionNo,userId,action);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    public String getTransactionNo() {
      return transactionNo;
    }

    public void setTransactionNo(String transactionNo) {
      this.transactionNo = transactionNo;
    }

    public String getUserId() {
      return userId;
    }

    public void setUserId(String userId) {
      this.userId = userId;
    }
  }

//创建线程池
  private static ExecutorService CUSTOMSDECLARE_THREAD_POOL = new ThreadPoolExecutor(
      2, 10, 5 * 60L,
      TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
      new ThreadFactory() {
        private final AtomicInteger threadNumber = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
          return new Thread(r,
              "schedule-pool-overseas-customsDeclare" + threadNumber.getAndIncrement());
        }
      }
  );

  public void synchCustomsDeclare(String transactionNo, String userId, Integer action) {
  	//调用execute时,将业务线程放入
    CUSTOMSDECLARE_THREAD_POOL
        .execute(new CustomsDeclareThread(transactionNo, userId, action));
  }

  /**
   *
   * @param transactionNo 支付单号
   * @param userId  用户id
   * @param action 1新增报关记录,2修改报关记录
   */
  public void  declareOrder(String transactionNo,String userId,Integer action){
    System.out.println(transactionNo + "+++++" + userId);
    List<PTbOrder> orderList = orderService.selectOrderByTransactionNo(transactionNo, userId);
    PTbTransaction tbTransaction = transactionService
        .selectTransactionByTransactionNo(transactionNo);
    for (PTbOrder pTbOrder : orderList) {
      String warehouseType = pTbOrder.getWarehouseType();
      if ("INBONDED".equals(warehouseType)) {
        //报关方式判断
        if ("EPAY_WX_APP".equals(tbTransaction.getPayMethod()) || "EPAY_WX_WEB"
            .equals(tbTransaction.getPayMethod())) {//网易支付报关
          log.info("++++网易支付跨境商品报关++++start" + transactionNo);
          epayService.customsDeclare(tbTransaction, pTbOrder, String.valueOf(action), true,
              tbTransaction.getPayMethod());
        } else if ("ALIPAY_GUOJI".equals(tbTransaction.getPayMethod())) {//国际支付宝报关
          log.info("++++支付宝支付跨境商品报关++++start" + transactionNo);
          alipayService
              .customsDeclare(tbTransaction, pTbOrder, true, tbTransaction.getPayMethod(),
                  action, false);
        } else if ("WXPAY".equals(tbTransaction.getPayMethod()) || "WXPAY_APP".equals(tbTransaction.getPayMethod()) || "WXLITE".equals(tbTransaction.getPayMethod())) {
          log.info("+++++原生微信支付报关+++++start");
          wxPayService.customsDeclare(tbTransaction, pTbOrder, true, tbTransaction.getPayMethod(),action);
        }
      }
    }
  }

}

文章开篇举例跨境报关的,就是调用的这个类的synchCustomsDeclare方法,在该方法中执行线程池的execute

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值