ThreadPoolExecutor 源码分析

线程池 ThreadPoolExecutor 源码详细分析 线程池 ThreadPoolExecutor 源码详细分析 1、线程池的作用 一方面当执行大量一步任务的时候线程池能够提供较好的性能,在不使用线程池的时候,每当需要执行异步的时候都是直接 new 一线程进行运行,而线程的创建和销毁都是需要开销的。使用线程池的时候,线程池里面的线程是可复用的,不会每次执行异步任务的时候都重新创建和销毁线程。 另一方面线程池提供了一种资源限制和管理的手段,比如可以限制线程的个数,动态新增线程等,每个 ThreadPoolExecutor 也保留了一些基本的统计数据,比如当前线程 阅读详情

线程池概述

线程池,是指管理一组同构工作线程的资源池。
线程池在工作队列(Work Queue)中保存了所有等待执行的任务。工作者线程(Work Thread)会从工作队列中获取一个任务并执行,然后返回线程池并等待下一个任务。

线程池比执行任务再创建线程会有以下优势:

  1. 节省资源。通过重用线程来省去在线程创建和销毁过程中产生的开销。
  2. 提高响应性。当执行请求到达时,工作线程通常已经存在,因此不需要等待线程创建,从而提高了响应性。
  3. 防止资源耗尽。通过调整线程池的大小,防止过多线程相互竞争资源。

ThreadPoolExecutor 是Java中线程池的实现类。下图是继承关系:

AbstractExecutorService

«Interface»

Executor

«Interface»

ExecutorService

ThreadPoolExecutor

  • Executor ,基于生产者-消费者模式,提交相当于生产者,执行任务相当于消费者。通过该模式将任务的提交与执行解耦开来。
  • ExecutorService,是Executor 的实现,该接口基于Executor 提供了生命周期的支持,例如任务的运行、关闭和中止,以及通过 submit 方法来创建一个异步任务 Future。
  • AbstractExecutorService,是ExecutorService 的实现,使得下层实现只需要关注任务的执行。
  • ThreadPoolExecutor,是Java中线程池的实现。

下图是ThreadPoolExecutor的大致结构

生命周期

Executor 的实现通常会创建线程来执行任务。由于 Executor 以异步的方式来执行任务,因此之前提交任务的状态不是立即可见的,有些任务已经完成,有些还在运行,有些在等待执行。当关闭应用程序时,是完成当前任务并不接受新任务,还是直接关闭所有任务(不管是在执行还是没有执行)。
为了解决执行服务的生命周期问题,Executor 扩展了 ExecutorService 接口,该接口提供了对生命周期管理的方法。

public interface ExecutorService extends Executor {void shutdown();List<Runnable> shutdownNow();boolean awaitTermination(long timeout, TimeUnit unit);boolean isShutdown();boolean isTerminated();// 以及一些用于创建异步任务的方法<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks);Future<?> submit(Runnable task);....}

在ThreadPoolExecutor中提供了五种状态:

下图是状态之间的转换关系:

如果任务队列被填满(在队列大小有限的情况下)或者某个任务被提交到一个已经被关闭的Executor中时应该怎么处理这些情况?JDK提供了一种策略来处理这些情况--饱和策略

在ThreadPoolExecutor中通过ctl字段来维护了线程池的运行状态和线程数量(工作者线程)

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

具体的可以通过两个参数来说明:

  • COUNT_BIT的值为29(32-3)
  • COUNT_MASK 则为高三位为0、低29位全1的字段
private static final int COUNT_BITS = Integer.SIZE - 3;private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;

每个状态的取值如下,每个取值都向左边移动了29位:

private static final int RUNNING    = -1 << COUNT_BITS;  private static final int SHUTDOWN   =  0 << COUNT_BITS;  private static final int STOP       =  1 << COUNT_BITS;  private static final int TIDYING    =  2 << COUNT_BITS;  private static final int TERMINATED =  3 << COUNT_BITS;

所以高三位用来表示线程池的状态
之后用来确定线程池中的线程数量都使用COUNT_MASK来计算,这样就能计算低29位

private static int workerCountOf(int c)  { return c & COUNT_MASK; }

ThreadPoolExecutor 通过如下的方法来检测当前线程池的状态:
运行是要比终结状态小的

// 当前状态要比给定的状态小,如 running < terminatedprivate static boolean runStateLessThan(int c, int s) {      return c < s;  }  // 当前状态要高于给定的状态,如 terminated >= runningprivate static boolean runStateAtLeast(int c, int s) {      return c >= s;  }  // 检测当前线程是否在运行private static boolean isRunning(int c) {      return c < SHUTDOWN;  }

饱和(拒绝)策略

ThreadPoolExecutor的饱和策略可以通过调用
setRejectedtExecutionHandler 来修改。
JDK 提供了几种不同的 RejectedExecutionHandler 的实现:

队列任务管理

如果请求速率超过了线程池的处理速率,那么新到来的请求将会累计起来,这些请求会在一个由 Executor 管理的 Runnable 队列(也就是任务队列 Work Queue)中等待。但这仍有可能超出缓存的数量。
基本的任务排队方法有三种:

  • 有界队列:有长度限制
  • 无界队列:没有长度限制
  • 同步移交:立即将元素传输给正在等待的消费者
    BlockingQueue 是ThreadPoolExecutor 的任务队列:
public interface BlockingQueue<E> extends Queue<E> {offer();pool();put();take();....}

JDK 提供了以下几种实现类:

工作者线程

所有的任务都是由工作者线程来执行的,那么工作者线程是如何执行这些任务的,以及线程池是如何维护工作者线程的。下面是ThreadPoolExecutor中的工作者线程类Worker

private final class Worker      extends AbstractQueuedSynchronizer      implements Runnable  {// 线程final Thread thread;// 第一个任务Runnable firstTask;// 执行任务的数量volatile long completedTasks;....}

工作者线程实现了Runnable接口,并且它包含了一个Thread ,说明工作者线程是一个特殊的任务也是一个线程,它可以去执行一些其他任务也可以自控制。

工作者线程继承自AQS,而不是使用的可重入锁ReentrantLock,目的是实现可不重入的特性(线程封闭)。每个工作者线程必须是线程封闭的。
在工作者线程构造器中有一段:

this.thread = getThreadFactory().newThread(this);

通过调用线程工厂创建线程并将this(也就是工作者线程)提交给Thread
也就是执行Thread就启动了自己,所以工作者线程可以自己管理自己
addWorkder中创建工作者线程之后执行了它,这里的t就是thread

t.start();  

线程池中的工作者线程的状态由两个字段来控制:

// 生存时间private volatile long keepAliveTime;// 是否允许核心线程超时等待private volatile boolean allowCoreThreadTimeOut;

keepAliveTime 是当线程数量大于核心线程数数量时工作者线程没有任务时存活的时间
例如当前工作者线程数量是30,核心线程数量上限是20,最大线程数量是30。那么多出来10个线程在线程池比较空闲的时候是需要清除的,因为这是占用了多余的系统资源。
keepAliveTime是为了保证突然之间线程池繁忙的情况,这时候就没必要立马清除这些线程,可以"等等看"有没有突发情况。

allowCoreThreadTimeOut 则是使得核心线程也受keepAliveTime的影响
这些具体体现在从队列中获取任务的时候,下面会详细描述

线程工厂

每当线程池创建一个线程,都是通过线程的工厂方法创建的。
默认的线程工厂方法创建一个新的、非守护的线程,并且不包含特殊的配置信息。通过制定一个工厂方法,可以定制线程池的配置信息。每当线程池需要一个新的线程都会调用getThreadFactory()这个方法。

以下是ThreadPoolExecutor 创建一个工作者线程,是通过工厂方法创建的:

Worker(Runnable firstTask) {      setState(-1); // inhibit interrupts until runWorker      this.firstTask = firstTask;      this.thread = getThreadFactory().newThread(this);  }

ThreadFactory 是一个接口

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

在构造线程池ThreadPoolExecutor时,可以传入一个线程工厂,使得创建线程时通过该线程工厂创建。

执行一个任务

ThreadPoolExecutor 是通过实现Executor来执行任务的
具体分为三个步骤:

  1. 如果当前正在运行的线程小于corePoolSize则创建一个工作者线程并将该任务作为该线程的第一个任务执行
  2. 如果当前任务能够进入任务队列,仍需要检查线程池的运行状态。如果线程池关闭则需要将任务交给饱和策略处理。如果没有关闭并且工作者线程为0,则需要创建工作者线程(这个时候任务已经在队列中)。
  3. 如果不能够进入队列,则尝试创建工作者线程去处理任务;如果失败则说明已经饱和,则将任务交给饱和(拒绝)策略处理。

copy from Java线程池实现原理及其在美团业务中的实践

通过源码来理解一下:

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);  }

当执行一个任务会将一个任务放到工作队列中或者是直接创建一个工作者线程去执行该任务。
addWorker 是创建一个工作者线程并运行一个任务的(可以不运行一个任务)
这段代码主要做两个工作:

  1. 保证能正常添加工作者线程,数量不能超过设定的范围并且线程池没有关闭。
  2. 向工作者线程组中添加一个工作者线程并且线程池在正常运行,之后运行该线程去执行任务。
private boolean addWorker(Runnable firstTask, boolean core) {  // 保证能添加工作者线程    retry:      for (int c = ctl.get();;) {          // Check if queue empty only if necessary.          if (runStateAtLeast(c, SHUTDOWN)              && (runStateAtLeast(c, STOP)                  || firstTask != null                  || workQueue.isEmpty()))              return false;            for (;;) {        // 如果超过限定数量,这个数量可以是最小的活跃线程数量可以是最大的活跃线程数量              if (workerCountOf(c)                  >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))                return false;              if (compareAndIncrementWorkerCount(c))              // 只有能增加工作者线程才退出                break retry;              //重新获取并检查运行状态            c = ctl.get();  // Re-read ctl              if (runStateAtLeast(c, SHUTDOWN))                  continue retry;              // else CAS failed due to workerCount change; retry inner loop          }      }  // 从这里创建一个工作者线程并运行该线程    boolean workerStarted = false;      boolean workerAdded = false;      Worker w = null;      try {          w = new Worker(firstTask);          final Thread t = w.thread;          if (t != null) {              final ReentrantLock mainLock = this.mainLock;              mainLock.lock();              try {              // 检测线程池运行状态                if (isRunning(c) ||                      (runStateLessThan(c, STOP) && firstTask == null)) {                    // 检测线程状态,线程状态必须为 NEW                    if (t.getState() != Thread.State.NEW)                          throw new IllegalThreadStateException();                      // 将该工作者线程添加到工作者线程组中                    workers.add(w);                      workerAdded = true;                      int s = workers.size();                      if (s > largestPoolSize)                          largestPoolSize = s;                  }              } finally {                  mainLock.unlock();              }              // 如果工作者线程已经添加则运行该线程            if (workerAdded) {                  t.start();                  workerStarted = true;              }          }      } finally {          if (! workerStarted)              addWorkerFailed(w);      }      return workerStarted;  }折叠 

获取并执行任务

工作者线程获取任务主要有两个途径:

  1. 通过创建工作者线程时给予的
  2. 从任务队列中获取的
    期间会一直检查线程池的状态。如果遇到线程池停止了需要去确保当前线程的中断状态如果线程池没有终止也需要确保线程能够正常运行
final void runWorker(Worker w) {      Thread wt = Thread.currentThread();      Runnable task = w.firstTask;      w.firstTask = null;      w.unlock(); // allow interrupts      boolean completedAbruptly = true;      try {      // 有两种情况    // 1. 执行firstTask    // 2. 获取一个任务并执行        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);                  try {                      task.run();                      afterExecute(task, null);                  } catch (Throwable ex) {                      afterExecute(task, ex);                      throw ex;                  }              } finally {                  task = null;                // 增加任务执行数量,这里是线程封闭的,所以不需要考虑并发的情况                  w.completedTasks++;                  w.unlock();              }          }          completedAbruptly = false;      } finally {      // 线程自回收        processWorkerExit(w, completedAbruptly);      }  }

从任务队列中获取任务

工作者线程通过 getTask获取一个任务来执行

private Runnable getTask() {      boolean timedOut = false; // Did the last poll() time out?        for (;;) {          int c = ctl.get();            // Check if queue empty only if necessary.          // 检测线程池状态,队列不能为空        if (runStateAtLeast(c, SHUTDOWN)              && (runStateAtLeast(c, STOP) || workQueue.isEmpty())) {              decrementWorkerCount();              return null;          }  //         int wc = workerCountOf(c);            // 这一段用来表示核心线程是否受影响        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;  // 工作者线程太多或者任务队列为空        if ((wc > maximumPoolSize || (timed && timedOut))              && (wc > 1 || workQueue.isEmpty())) {              // 减少工作者线程数量            if (compareAndDecrementWorkerCount(c))                  return null;              continue;          }  // 从队列中获取一个任务        try {          // 这一段体现了keepAliveTime的作用        // 超过keepAliveTime给定时间没有获取到任务,那么线程将会被清理/回收掉            Runnable r = timed ?                  workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :                  workQueue.take();              if (r != null)                  return r;              timedOut = true;          } catch (InterruptedException retry) {              timedOut = false;          }      }  }

工作者线程回收

processWorkerExit 负责这一工作,具体流程如下:

  1. 从工作者线程集合中移除
  2. 尝试终止线程池
  3. 尝试通过创建一个工作者线程来替换当前线程,这种情况可能由以下原因当前被清除的线程可能由任务异常而退出没有工作者线程执行任务队列中没有任务
private void processWorkerExit(Worker w, boolean completedAbruptly) {      if (completed
关于发那科机器人抓手及物料搬运阀配置 4:确保抓手阀岛和输入模块配网连接正常,MENU—SETUP—MH Valves—Details,详细界面进入到左上图所示,根据每组阀分配夹钳数量并应用。3:设置搬运有效,抓手是否带点焊可以自行选择,要设置应用选择,物料搬用工具数量,工具上阀岛的数量,夹钳存在数量,工具存在数量,以及真空吸盘,冷启动。​2:MENU—应用选择,将搬运置为有效,剩余其他项根据机器人实际用途进行选择。5:设置夹钳数量,检查打开夹钳,检查闭合夹钳,延迟时间要给选择配置应用。 阅读详情

相关推荐

如何在win11中用双硬盘或移动硬盘装Ubuntu 20.04 双系统

win11 安装双系统

qq_42817360的博客 5137

ThreadPoolExecutor源码分析

一、线程和任务的概念 首先区分概念,任务和线程。可以简单理解为任务为Runnable,线程为Thread。ThreadPoolExecutor内部维持的是线程池,因为创建线程比较耗时耗资源。而内部维护任务使用的是BlockingQueue。 二、ThreadPoolExecutor源码 2.1 ctl变量 private final AtomicInteger ctl = ...

meser88的博客 1044

全国30米分辨率逐年植被覆盖度(FVC)数据集

植被覆盖度是描述地表植被的重要参数与生态环境的基本指标,在大气圈、土壤圈、水圈和生物圈中都占据着重要的地位,区域及全球范围的植被覆盖度估算对植被及相关领域的研究具有重要意义。分别对LANDSAT 5/7/8系列数据计算FVC,其中Landsat5 和Landsat 7NDVI计算利用 B4和B3波段,Landsat8 和Landsat9 NDVI计算利用 B5和B4波段。算法从当年所有观测数据中,以低云、低探测角度和最高NDVI值为标准,选择最佳的可用像元值,并进行换算。(3) FVC的计算。

地球资源数据云的官方博客 1808

【线程池】史上最全的ThreadPoolExecutor源码详解

史上最全的ThreadPoolExecutor源码详解,一篇文章带你彻底搞懂ThreadPoolExecutor底层原理。

小七的博客 3969

DSSP 工具:蛋白质二级结构信息计算与批量处理教程

DSSP(Dictionary of Secondary Structure in Proteins)是一款经典的蛋白质二级结构计算工具,由荷兰癌症研究所(NKI Research)Perrakis 团队维护。它通过分析蛋白质的 PDB 结构文件,能够自动标注每个氨基酸残基的二级结构类型、相对溶剂可及性(暴露面积)等关键信息,为后续的拓扑图绘制、疏水 / 亲水表面分析、二级结构预测模型训练等提供核心数据支持。

good_rrrrr的博客 1835

基于DFT的mbist sdc模板(DFT)

摘要:本文详细介绍了DFT测试模式下的SDC约束方法。

murphyrong的博客 920

线程池(ThreadPoolExecutor)源码解析

目录一、线程池概念介绍1.1、什么是线程池1.2、线程池工作流程1.3、线程池的代码用例二、源码解析——构造函数2.1、线程池的构造函数及类的继承关系2.2、Executors提供的线程池模板2.3、拒绝策略的实现2.4、任务队列BlockingQueue的实现三、 源码解析——execute(Runnable command)3.1、流程概述 一、线程池概念介绍 1.1、什么是线程池 池化技术其实在技术生态圈中是比较常见的,比如:对象池、连接池等等。 为什么会有线程池这个东西存在呢?其实原因跟其他池化技

小志的博客 8746

C#通过Aforge调用电脑摄像头(附代码)

C#标准库本身不带有能调用电脑摄像头的库,如果利用windows自身的API来实现的话,着实有些麻烦。Aforge这个第三方库能很好的实现调用、处理的功能。 PS:文末给大家分享了完整的项目源码,各位最好先下载下来,对照着来看 1、先看一下效果 2、Aforge介绍 AForge.NET是一个专门为开发者和研究者基于C#框架设计的,这个框架提供了不同的类库和关于类库的资源,还有很多应用程序例子,包括计算机视觉与人工智能,图像处理,神经网络,遗传算法,机器学习,机器人等领域。 3、我使用的开发环境 操作系统

weixin_44996090的博客 1万+

ThreadPoolExecutor 源码分析 - execute() 方法

知识回顾 线程池的几种状态 RUNNING 、SHUTDOWN 等 线程池的核心参数 corePoolSize 和 maximumPoolSize 等 线程池的工作原理 核心线程 -> 阻塞队列 -> 非核心线程 -> 拒绝策略 如何判断线程池的状态和线程数量:通过 AtomicInteger ctl 变量的高低位判断 Worker 对象的介绍(对一个线程任务的包装) ThreadPoolExecutor#workers 属性 线程池中有一个 workers 集合,里面记录了所有的工作

nimo10050的博客 860

手把手教你学Simulink实例--基于simulink搭建起一个基础的矩阵变换器仿真模型

矩阵变换器(Matrix Converter, MC)是一种直接将交流电源转换为另一频率和幅值的交流电源的电力电子设备,它不需要中间的直流环节。这种变换器通过控制一组双向开关来实现对输入电压的精确控制,从而产生所需的输出电压波形。Simulink提供了强大的仿真环境,可以用于设计、分析和验证基于矩阵变换器的电源系统。

MHD0815的博客 337

《一》:LBE,VR 大空间系列——场景环境需求解析

当前,大量 VR 体验活动在室内场地开展。因此,对于场地照明有特定要求:除天花板外,场地的所有表面均需有照明覆盖。这是为了保证玩家无论处于场地的哪个位置,地面与墙面都不会出现明显的影子。场地内不建议安装射灯或高强度的点光源,若已安装此类灯具,需使用柔光板进行遮盖。此外,要避免在阳光下使用 VR 设备台。参考图(请忽略其中Maker标签)

unitygroup的博客 942

java线程池ThreadPoolExecutor原理源码分析

java线程池实现原理,线程池远吗分析

qq_34735262的博客 1848

国产数据库全解析:openGauss、OceanBase、TiDB与KingbaseES的核心优势与应用场景指南

本文将深入剖析openGauss、OceanBase、TiDB和KingbaseES这四款主流国产数据库的核心内容,并针对国产化过程中给出使用建议,以帮助企业根据自身需求选择合适的数据库解决方案。国产数据库在性能、扩展性、兼容性、安全性等方面展现出强大实力,能够满足不同行业、不同场景的需求。企业在进行国产化过程中,应充分考虑业务特点、技术栈、团队能力等因素,结合上述分析,选择最适合自身的国产数据库产品。随着国产数据库技术的持续发展与生态完善,它们将成为推动企业数字化转型、保障数据安全的重要力量。

java专栏 8779

ThreadPoolExecutor类源码分析

Java中的线程池通过复用线程来提高多线程任务的执行效率,而ThreadPoolExecutor就是Java中线程池的核心类之一,它将线程的创建、管理以及资源调度进行了封装,使用ThreadPoolExecutor能够方便地管理多个线程的生命周期和执行。

一名Java语言狂热分子。 923

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

ThreadPoolExecutor底层源码分析

ThreadPoolExecutor底层源码分析

qq_40344505的博客 1177

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

ThreadPoolExecutor结合源码分析运行原理

ThreadPoolExecutor源码分析核心接口ExecutorExecutorServiceAbstractExecutorService源码分析内部工作原理构造方法赋值属性分析内部工作类Worker线程池运行思路Worker类源码分析构造方法addWorker方法分析run方法runWorker方法getTask方法processWorkerExit方法tryTerminate方法shutdown方法shutdownNow方法interruptIdleWorkers方法interruptIfStar

j222085的博客 174

Java ThreadPoolExecutor线程池原理及源码分析

一、源码分析(基于JDK1.6) ThreadExecutorPool是使用最多的线程池组件,了解它的原始资料最好是从从设计者(Doug Lea)的口中知道它的来龙去脉。在Jdk1.6中,ThreadPoolExecutor直接继承了AbstractExecutorService,并层级实现了ExecutorService和Executor接口。 1.Executor Executor是

Schelor的专栏 3033

Java ThreadPoolExecutor 源码分析

1.背景    了解过Java线程池的同学一定对Executors不陌生,我们可以用它的静态方法很快的创建出我们需要的线程池,比如:我们需要一个固定数目的线程池,那么可以这样:     Executors.newFixedThreadPool(5)  创建一个只有5个线程的线程池。也可以通过:     Executors.newCachedThreadPool()  创建一个没有数量限制的线程池。...

爱技术,爱生活 319

线程池ThreadPoolExecutor源码分析(一)

其中线程工厂和拒绝策略有默认值,其它均需要自己定义,不需要定义这两个调用另外的构造方法即可,这里就不在贴原码了。从中可以看出线程池任务执行最终还是调用execute。线程池任务添加处理流程图。

qq_41184048的博客 260
上一篇: springboot配置 Druid 数据源及密码加密
下一篇: springcloud环境搭建
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值