Java ThreadPoolExecutor的参数深入理解

Java ThreadPoolExecutor的参数深入理解

一、使用Executors创建线程池   

之前创建线程的时候都是用的Executors的newFixedThreadPool(),newSingleThreadExecutor(),newCachedThreadPool()这三个方法。当然Executors也是用不同的参数去new ThreadPoolExecutor

    1. newFixedThreadPool()

创建线程数固定大小的线程池。 由于使用了LinkedBlockingQueue所以maximumPoolSize 没用,当corePoolSize满了之后就加入到LinkedBlockingQueue队列中。每当某个线程执行完成之后就从LinkedBlockingQueue队列中取一个。所以这个是创建固定大小的线程池。

 public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                   0L, TimeUnit.MILLISECONDS,
                   new LinkedBlockingQueue<Runnable>());
  }
 public ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               long keepAliveTime,
               TimeUnit unit,
               BlockingQueue<Runnable> workQueue) {
   this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
       Executors.defaultThreadFactory(), defaultHandler);
  }

   2.newSingleThreadPool()

创建线程数为1的线程池,由于使用了LinkedBlockingQueue所以maximumPoolSize 没用,corePoolSize为1表示线程数大小为1,满了就放入队列中,执行完了就从队列取一个。

 public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
      (new ThreadPoolExecutor(1, 1,
                  0L, TimeUnit.MILLISECONDS,
                  new LinkedBlockingQueue<Runnable>()));
  }

    3.newCachedThreadPool()

创建可缓冲的线程池。没有大小限制。由于corePoolSize为0所以任务会放入SynchronousQueue队列中,SynchronousQueue只能存放大小为1,所以会立刻新起线程,由于maxumumPoolSize为Integer.MAX_VALUE所以可以认为大小为2147483647。受内存大小限制。

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                   60L, TimeUnit.SECONDS,
                   new SynchronousQueue<Runnable>());
  }
public ThreadPoolExecutor(int corePoolSize,
             int maximumPoolSize,
             long keepAliveTime,
             TimeUnit unit,
             BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
       Executors.defaultThreadFactory(), defaultHandler);
  }

二、使用ThreadPoolExecutor创建线程池

ThreadPoolExecutor的构造函数

 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.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
  }

参数:

1、corePoolSize核心线程数大小,当线程数<corePoolSize ,会创建线程执行runnable

2、maximumPoolSize 最大线程数, 当线程数 >= corePoolSize的时候,会把runnable放入workQueue中

3、keepAliveTime  保持存活时间,当线程数大于corePoolSize的空闲线程能保持的最大时间。

4、unit 时间单位

5、workQueue 保存任务的阻塞队列

6、threadFactory 创建线程的工厂

7、handler 拒绝策略

任务执行顺序:

1、当线程数小于corePoolSize时,创建线程执行任务。

2、当线程数大于等于corePoolSize并且workQueue没有满时,放入workQueue中

3、线程数大于等于corePoolSize并且当workQueue满时,新任务新建线程运行,线程总数要小于maximumPoolSize

4、当线程总数等于maximumPoolSize并且workQueue满了的时候执行handler的rejectedExecution。也就是拒绝策略。

ThreadPoolExecutor默认有四个拒绝策略:

1、ThreadPoolExecutor.AbortPolicy()   直接抛出异常RejectedExecutionException

2、ThreadPoolExecutor.CallerRunsPolicy()    直接调用run方法并且阻塞执行

3、ThreadPoolExecutor.DiscardPolicy()   直接丢弃后来的任务

4、ThreadPoolExecutor.DiscardOldestPolicy()  丢弃在队列中队首的任务

当然可以自己继承RejectedExecutionHandler来写拒绝策略.

int corePoolSize = 1;
 int maximumPoolSize = 2;
 int keepAliveTime = 10;
// BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
 BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5);
 ThreadFactory threadFactory = Executors.defaultThreadFactory();
 //线程池和队列满了之后的处理方式
 //1.跑出异常
 RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
 RejectedExecutionHandler handler2 = new ThreadPoolExecutor.CallerRunsPolicy();
 RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardPolicy();
 RejectedExecutionHandler handler4 = new ThreadPoolExecutor.DiscardOldestPolicy();

 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory, handler2);

 for (int j = 1; j < 15; j++) {
  threadPoolExecutor.execute(new Runnable() {

  public void run() {

   try {
   System.out.println(Thread.currentThread().getName());
   TimeUnit.SECONDS.sleep(1);
   } catch (InterruptedException e) {
   e.printStackTrace();
   }

  }
  });
 }

 System.out.println(threadPoolExecutor);

 }

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • java中Executor,ExecutorService,ThreadPoolExecutor详解

    java中Executor,ExecutorService,ThreadPoolExecutor详解 1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thre

  • java多线程并发executorservice(任务调度)类

    复制代码 代码如下: package com.yao; import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ScheduledFuture;import java.util.concurrent.TimeUnit; /** * 以下是一个带方法的类,它设置了 ScheduledExecutorService ,2

  • java ThreadPoolExecutor 并发调用实例详解

    java ThreadPoolExecutor 并发调用实例详解 概述 通常为了提供任务的处理速度,会使用一些并发模型,ThreadPoolExecutor中的invokeAll便是一种. 代码 package test.current; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util

  • Java 线程池ExecutorService详解及实例代码

    Java 线程池ExecutorService 1.线程池 1.1什么情况下使用线程池 单个任务处理的时间比较短. 将需处理的任务的数量大. 1.2使用线程池的好处 减少在创建和销毁线程上所花的时间以及系统资源的开销. 如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及"过度切换"; 2.ExecutorService和Executors 2.1简介 ExecutorService是一个接口,继承了Executor, public interface ExecutorS

  • java ExecutorService使用方法详解

    下面的例子主要讨论两个问题: 问题1.线程池固定大小,假设为5.那么向线程池放入10个线程,运行效果如何?其他线程的状态? 问题2.那么如何从线程池中移除某一个线程,确切说是使某一个线程成为空闲线程? 例子: package com.dada.executorService; import java.util.concurrent.TimeUnit; public class JobThread extends Thread { // 为线程命名 public JobThread(String

  • 详解Java利用ExecutorService实现同步执行大量线程

    自从java1.5以后,官网就推出了Executor这样一个类,这个类,可以维护我们的大量线程在操作临界资源时的稳定性. 先上一段代码吧: TestRunnable.java public class TestRunnable implements Runnable { private String name; public TestRunnable(String name) { this.name = name; } @Override public void run() { while (t

  • java 中ThreadPoolExecutor原理分析

    java 中ThreadPoolExecutor原理分析 线程池简介 Java线程池是开发中常用的工具,当我们有异步.并行的任务要处理时,经常会用到线程池,或者在实现一个服务器时,也需要使用线程池来接收连接处理请求. 线程池使用 JDK中提供的线程池实现位于java.util.concurrent.ThreadPoolExecutor.在使用时,通常使用ExecutorService接口,它提供了submit,invokeAll,shutdown等通用的方法. 在线程池配置方面,Executor

  • Java并发编程中使用Executors类创建和管理线程的用法

    1. 类 Executors Executors类可以看做一个"工具类".援引JDK1.6 API中的介绍:   此包中所定义的 Executor.ExecutorService.ScheduledExecutorService.ThreadFactory 和 Callable 类的工厂和实用方法.此类支持以下各种方法: (1)创建并返回设置有常用配置字符串的 ExecutorService 的方法. (2)创建并返回设置有常用配置字符串的 ScheduledExecutorServi

  • 理解java多线程中ExecutorService使用

    java.util.concurrent包里提供了关于多线程操作的类,平常用的比较多的是ExecutorService及其实现类(如ThreadPoolExecutor等),Executor,Executors,Future,Callable等 1. ExecutorService(继承自Executor)接口:提供了一些异步的多线程操作方法,如execute(), submit(), shutdown(), shutdownNow()等 2. Executor接口:执行提交的任务(线程),只有

  • Java中Executor接口用法总结

    本文实例讲述了Java中Executor接口用法.分享给大家供大家参考.具体如下: 1.Java中Executor接口的定义 public interface Executor { void execute(Runnable command); } 2.Executors以下静态工厂方法创建一个线程池: a) newFixedThreadPool:创建一个定长的线程池.达到最大线程数后,线程数不再增长. 如果一个线程由于非预期Exception而结束,线程池会补充一个新的线程. b) newCa

  • Java Executor 框架的实例详解

    Java Executor 框架的实例详解 大多数并发都是通过任务执行的方式来实现的. 一般有两种方式执行任务:串行和并行. class SingleThreadWebServer { public static void main(String[] args) throws Exception { ServerSocket socket = new ServerSocket(80); while(true) { Socket conn = socket.accept(); handleRequ

  • java ThreadPoolExecutor使用方法简单介绍

    java  ThreadPoolExecutor 前言: 在项目中如果使用发短信这个功能,一般会把发短信这个动作变成异步的,因为大部分情况下,短信到底是发送成功或者失败,都不能影响主流程.当然像发送MQ消息等操作也是可以封装成异步操作的. 使用基本的New Thread 如果想一个操作变成异步的,可以直接new thread,然后在run方法中实现业务操作即可.例如: new Thread(new Runnable() { public void run() { //发短信.发MQ消息等 } }

随机推荐