细讲Java线程池Executor

一文搞懂线程池原理——Executor框架详解 文章目录1 使用线程池的好处2 Executor 框架2.1 Executor 框架结构2.2 Executor 框架使用示意图2.3 Executor 框架成员2.3.1 Executor 与 ExecutorService2.3.2 Future接口2.3.3 Runnable接口和Callable接口2.3.4 Executors创建线程池3 ThreadPoolExecutor 详解3.1 线程池状态转换3.2 线程池处理流程3.2.1 execute()方法3.2.2 Worker线程管理3.2. 阅读详情

线程池类图

我们最常使用的Executors实现创建线程池使用线程主要是用上述类图中提供的类。在上边的类图中,包含了一个Executor框架,它是一个根据一组执行策略的调用调度执行和控制异步任务的框架,目的是提供一种将任务提交与任务如何运行分离开的机制。它包含了三个executor接口:

  • Executor:运行新任务的简单接口
  • ExecutorService:扩展了Executor,添加了用来管理执行器生命周期和任务生命周期的方法
  • ScheduleExcutorService:扩展了ExecutorService,支持Future和定期执行任务

线程池的好处

  • 降低资源消耗 -重用存在的线程,减少对象创建、消亡的开销,性能好
  • 提高响应速度 -可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。当任务到达时,任务可不用等待线程创建就能立即执行
  • 提高线程的可管理性 -提供定时执行、定期执行、单线程、并发数控制等功能。

new Thread的弊端

  • 每次new Thread 新建对象,性能差
  • 线程缺乏统一管理,可能无限制的新建线程,相互竞争,可能占用过多的系统资源导致死机或者OOM(out of memory 内存溢出),这种问题的原因不是因为单纯的new一个Thread,而是可能因为程序的bug或者设计上的缺陷导致不断new Thread造成的。
  • 缺少更多功能,如更多执行、定期执行、线程中断。

线程池核心类-ThreadPoolExecutor

参数说明:ThreadPoolExecutor一共有七个参数,这七个参数配合起来,构成了线程池强大的功能。

  • corePoolSize :核心线程数量
  • maximumPoolSize :线程最大线程数
  • workQueue :阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响
    • 当我们提交一个新的任务到线程池,线程池会根据当前池中正在运行的线程数量来决定该任务的处理方式。处理方式有三种: 1、直接切换(SynchronusQueue) 2、无界队列(LinkedBlockingQueue)能够创建的最大线程数为corePoolSize,这时maximumPoolSize就不会起作用了。当线程池中所有的核心线程都是运行状态的时候,新的任务提交就会放入等待队列中。 3、有界队列(ArrayBlockingQueue)最大maximumPoolSize,能够降低资源消耗,但是这种方式使得线程池对线程调度变的更困难。因为线程池与队列容量都是有限的。所以想让线程池的吞吐率和处理任务达到一个合理的范围,又想使我们的线程调度相对简单,并且还尽可能降低资源的消耗,我们就需要合理的限制这两个数量 分配技巧: [如果想降低资源的消耗包括降低cpu使用率、操作系统资源的消耗、上下文切换的开销等等,可以设置一个较大的队列容量和较小的线程池容量,这样会降低线程池的吞吐量。如果我们提交的任务经常发生阻塞,我们可以调整maximumPoolSize。如果我们的队列容量较小,我们需要把线程池大小设置的大一些,这样cpu的使用率相对来说会高一些。但是如果线程池的容量设置的过大,提高任务的数量过多的时候,并发量会增加,那么线程之间的调度就是一个需要考虑的问题。这样反而可能会降低处理任务的吞吐量。]
  • keepAliveTime :线程没有任务执行时最多保持多久时间终止(当线程中的线程数量大于corePoolSize的时候,如果这时没有新的任务提交核心线程外的线程不会立即销毁,而是等待,直到超过keepAliveTime)
  • unit :keepAliveTime的时间单位
  • threadFactory :线程工厂,用来创建线程,有一个默认的工场来创建线程,这样新创建出来的线程有相同的优先级,是非守护线程、设置好了名称)
  • rejectHandler :当拒绝处理任务时(阻塞队列满)的策略(AbortPolicy默认策略直接抛出异常、CallerRunsPolicy用调用者所在的线程执行任务、DiscardOldestPolicy丢弃队列中最靠前的任务并执行当前任务、DiscardPolicy直接丢弃当前任务)

corePoolSize、maximumPoolSize、workQueue 三者关系:如果运行的线程数小于corePoolSize的时候,直接创建新线程来处理任务。即使线程池中的其他线程是空闲的。如果运行中的线程数大于corePoolSize且小于maximumPoolSize时,那么只有当workQueue满的时候才创建新的线程去处理任务。如果corePoolSize与maximumPoolSize是相同的,那么创建的线程池大小是固定的。这时有新任务提交,当workQueue未满时,就把请求放入workQueue中。等待空线程从workQueue取出任务。如果workQueue此时也满了,那么就使用另外的拒绝策略参数去执行拒绝策略。

初始化方法:由七个参数组合成四个初始化方法

其他方法:

<pre class="prettyprint hljs less" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">execute(); //提交任务,交给线程池执行 
submit();//提交任务,能够返回执行结果 execute+Future
shutdown();//关闭线程池,等待任务都执行完
shutdownNow();//关闭线程池,不等待任务执行完
getTaskCount();//线程池已执行和未执行的任务总数
getCompleteTaskCount();//已完成的任务数量
getPoolSize();//线程池当前的线程数量
getActiveCount();//当前线程池中正在执行任务的线程数量

线程池生命周期:

  • running:能接受新提交的任务,也能处理阻塞队列中的任务
  • shutdown:不能处理新的任务,但是能继续处理阻塞队列中任务
  • stop:不能接收新的任务,也不处理队列中的任务
  • tidying:如果所有的任务都已经终止了,这时有效线程数为0
  • terminated:最终状态

使用Executors创建线程池

使用Executors可以创建四种线程池:分别对应上边提到的四种线程池初始化方法

Executors.newCachedThreadPool

newCachedThreadPool是一个根据需要创建新线程的线程池,当一个任务提交时,corePoolSize为0不创建核心线程,SynchronousQueue是一个不存储元素的队列,可以理解为队里永远是满的,因此最终会创建非核心线程来执行任务。 对于非核心线程空闲60s时将被回收。因为Integer.MAX_VALUE非常大,可以认为是可以无限创建线程的,在资源有限的情况下容易引起OOM异常。

<pre class="prettyprint hljs cpp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//创建newCachedThreadPool线程池源码
public static ExecutorService newCachedThreadPool() {
        /**
        *corePoolSize: 0,核心线程池的数量为0
        *maximumPoolSize:  Integer.MAX_VALUE,可以认为最大线程数是无限的
        *keepAliveTime: 60L
        *unit: 秒
        *workQueue: SynchronousQueue
        **/
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

使用案例:

<pre class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {
    ExecutorService executor = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        final int index = i;
        executor.execute(new Runnable() {
            @Override
            public void run() {
                log.info("task:{}",index);
            }
        });
    }
}

值得注意的一点是,newCachedThreadPool的返回值是ExecutorService类型,该类型只包含基础的线程池方法,但却不包含线程监控相关方法,因此在使用返回值为ExecutorService的线程池类型创建新线程时要考虑到具体情况。

Executors.newSingleThreadExecutor

newSingleThreadExecutor是单线程线程池,只有一个核心线程,用唯一的一个共用线程执行任务,保证所有任务按指定顺序执行(FIFO、优先级…)

<pre class="prettyprint hljs cpp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//newSingleThreadExecutor创建线程池源码
public static ExecutorService newSingleThreadExecutor() {
    /**
      *  corePoolSize : 1,核心线程池的数量为1

      *  maximumPoolSize : 1,只可以创建一个非核心线程

      *  keepAliveTime : 0L

      *  unit => 秒

      *  workQueue => LinkedBlockingQueue
      **/
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

当一个任务提交时,首先会创建一个核心线程来执行任务,如果超过核心线程的数量,将会放入队列中,因为LinkedBlockingQueue是长度为Integer.MAX_VALUE的队列,可以认为是无界队列,因此往队列中可以插入无限多的任务,在资源有限的时候容易引起OOM异常,同时因为无界队列,maximumPoolSize和keepAliveTime参数将无效,压根就不会创建非核心线程。

Executors.newFixedThreadPool

定长线程池,核心线程数和最大线程数由用户传入,可以设置线程的最大并发数,超出在队列等待

<pre class="prettyprint hljs cpp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//newFixedThreadPool创建线程池源码
public static ExecutorService newFixedThreadPool(int nThreads) {
        /**
          *  corePoolSize : 核心线程的数量为自定义输入nThreads

          *  maximumPoolSize : 最大线程的数量为自定义输入nThreads

          *  keepAliveTime : 0L

          *  unit : 秒

          *  workQueue : LinkedBlockingQueue
          **/
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newFixedThreadPool和SingleThreadExecutor类似,唯一的区别就是核心线程数不同,并且由于使用的是LinkedBlockingQueue,在资源有限的时候容易引起OOM异常。

Executors.newScheduledThreadPool

定长线程池,核心线程数由用户传入,支持定时和周期任务执行

<pre class="prettyprint hljs cpp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">//newScheduledThreadPool创建线程池源码
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    /**
      *  corePoolSize : 核心线程的数量为自定义输入corePoolSize

      *  maximumPoolSize : 最大线程的数量为Integer.MAX_VALUE

      *  keepAliveTime : 0L

      *  unit : 纳秒

      *  workQueue : DelayedWorkQueue
      **/
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

当一个任务提交时,corePoolSize为自定义输入,首先创建核心线程,核心线程满了之后,因此最终会创建非核心线程来执行任务。非核心线程使用后将被回收。因为Integer.MAX_VALUE非常大,可以认为是可以无限创建线程的,在资源有限的情况下容易引起OOM异常。因为使用的DelayedWorkQueue可以实现定时和周期任务。 ScheduledExecutorService提供了三种方法可以使用:

schedule:延迟后执行任务 scheduleAtFixedRate:以指定的速率执行任务 scheduleWithFixedDelay:以指定的延迟执行任务 使用案例:

<pre class="prettyprint hljs cpp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String[] args) {

        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

//        executorService.schedule(new Runnable() {
//            @Override
//            public void run() {
//                log.warn("schedule run");
//            }
//         //延迟3秒后执行
//        }, 3, TimeUnit.SECONDS);
        //        executorService.shutdown();

//        executorService.scheduleWithFixedDelay(new Runnable() {
//            @Override
//            public void run() {
//                log.warn("scheduleWithFixedDelay run");
//            }
//            //延迟一秒后每隔3秒执行
//        }, 1, 3, TimeUnit.SECONDS);

        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                log.warn("schedule run");
            }
            //延迟一秒后每隔3秒执行
        }, 1, 3, TimeUnit.SECONDS);

        /**
         * 定时器调度,不推荐使用,推荐ScheduledExecutorService调度
         */
//        Timer timer = new Timer();
//        timer.schedule(new TimerTask() {
//            @Override
//            public void run() {
//                log.warn("timer run");
//            }
//        //从当前时间每隔5秒执行
//        }, new Date(), 5 * 1000);
    }

总结

  • FixedThreadPool和SingleThreadExecutor 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而引起OOM异常
  • CachedThreadPool 和newScheduledThreadPool允许创建的线程数为Integer.MAX_VALUE,可能会创建大量的线程,从而引起OOM异常

这就是为什么禁止使用Executors去创建线程池,而是推荐自己去创建ThreadPoolExecutor的原因

如何定义线程池参数

CPU密集型 :线程池的大小推荐为CPU数量 + 1,CPU数量可以根据Runtime.availableProcessors方法获取 IO密集型 : CPU数量 * CPU利用率 * (1 + 线程等待时间/线程CPU时间) 混合型 : 将任务分为CPU密集型和IO密集型,然后分别使用不同的线程池去处理,从而使每个线程池可以根据各自的工作负载来调整 阻塞队列 : 推荐使用有界队列,有界队列有助于避免资源耗尽的情况发生 拒绝策略 : 默认采用的是AbortPolicy拒绝策略,直接在程序中抛出RejectedExecutionException异常【因为是运行时异常,不强制catch】,这种处理方式不够优雅。处理拒绝策略有以下几种比较推荐:

  • 在程序中捕获RejectedExecutionException异常,在捕获异常中对任务进行处理。针对默认拒绝策略
  • 使用CallerRunsPolicy拒绝策略,该策略会将任务交给调用execute的线程执行【一般为主线程】,此时主线程将在一段时间内不能提交任何任务,从而使工作线程处理正在执行的任务。此时提交的线程将被保存在TCP队列中,TCP队列满将会影响客户端,这是一种平缓的性能降低
  • 自定义拒绝策略,只需要实现RejectedExecutionHandler接口即可
  • 如果任务不是特别重要,使用DiscardPolicy和DiscardOldestPolicy拒绝策略将任务丢弃也是可以的

如果使用Executors的静态方法创建ThreadPoolExecutor对象,可以通过使用Semaphore对任务的执行进行限流也可以避免出现OOM异常

Java 并发编程—— Executors 分析应用,阿里架构师深入讲解Java开发 950)][外链图片转存中…(img-FIrcADYT-1711049786951)][外链图片转存中…(img-4AC4OlCe-1711049786951)]由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)[外链图片转存中…(img-mQ2lFL5Z-1711049786952)][外链图片转存中…(img-eLBkm3kU-1711049786952)] 阅读详情

相关推荐

线程池Executor框架解读

目录`Executor` 整体架构 Executor 整体架构 接口/类说明Executor该接口只有一个execute方法,目的是将任务提交和执行解耦ExecutorService该接口对Executor接口进行了拓展,定义了对线程池中线程的管理方法AbstractExecutorService对ExecutorService接口中部分方法的实现ThreadPoolExecutor线程池的最终实现,实现了线程池工作的完整机制,是整个框架的重点ForkJoinPool实现了Fork/Join模式的线程池S

桐花思雨 646

Java线程池Executor详解

线程池的大小推荐为CPU数量 + 1,CPU数量可以根据Runtime.availableProcessors方法获取CPU数量 * CPU利用率 * (1 + 线程等待时间/线程CPU时间)将任务分为CPU密集型和IO密集型,然后分别使用不同的线程池去处理,从而使每个线程池可以根据各自的工作负载来调整推荐使用有界队列,有界队列有助于避免资源耗尽的情况发生。

jcc4261的博客 1552

Java中ExecutorService线程池的使用(Runnable和Callable多线程实现)

线程的创建和释放,需要占用不小的内存和资源。如果每次需要使用线程时,都new 一个Thread的话,难免会造成资源的浪费,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源导致系统瘫痪。不利于扩展,比如如定时执行、定期执行、线程中断,所以很有必要了解下ExecutorService的使用。ExecutorService是Java提供的线程池,也就是说,每次我们需要使用线程的时候,可以通过ExecutorService获得线程。...

BADAO_LIUMANG_QIZHI的博客 8210

Java笔试面试-Executors

Executors 可以创建以下六种线程池: FixedThreadPool(n):创建一个数量固定的线程池,超出的任务会在队列中等待空闲的线程,可用于控制程序的最大并发数。 CachedThreadPool():短时间内处理大量工作的线程池,会根据任务数量产生对应的线程,并试图缓存线程以便重复使用,如果限制 60 秒没被使用,则会被移除缓存。 SingleThreadExecutor():创建...

HenryLei的博客 2万+

高通camx架构学习(零)—— 深入理解Camera 硬件抽象层

从上面的定义可以看出,主要是通过hw_module_t 代表了模块,通过其open方法用来打开一个设备,而该设备是用hw_device_t来表示,其中除了用来关闭设备的close方法外,并无其它方法,由此可见谷歌定义的HAL接口,并不能满足绝大部分HAL模块的需要,所以谷歌想出了一个比较好的解决方式,那便是将这两个基本结构嵌入到更大的结构体内部,同时在更大的结构内部定义了各自模块特有的方法,用于实现模块的功能,这样,一来对上保持了HAL的统一规范,二来也扩展了模块的功能。

图像学习之旅 1667

科研人必备!用WisPaper搭建个人文献知识库的完整指南(附Zotero联动技巧)

本文详细介绍了如何利用WisPaper搭建高效的个人文献知识库,包括文件命名标准化、文件夹结构设计、语义搜索技巧及与Zotero的深度联动方法。通过智能标签系统和知识图谱功能,科研人员可以快速定位关键文献,提升研究效率。特别适合需要管理大量学术文献的研究者。

weixin_30823001的博客 266

java 线程池Executor框架

Executor框架的介绍

骑牛小道士 1274

[多智能体强化学习] 王树森YouTube课程笔记

前言 近期在设计V2X资源分配任务下的状态空间和动作空间,可以说是一筹莫展,是自己菜,现在看来可能也是涉及到一些关于多智能体强化学习实现过程中过于细节的点,目前的知识储备还不够。因此打算用半周到一周的时间重电,希望之后能有进展。 本文内容来自于友人LX所推荐的油管教程,链接如下:多智能体强化学习,一共两节课40min左右。教程废话不多干货不少,老师的声音还好听,推荐直接去看原教程。 这里还要多一嘴,那就是对于强化学习来说,单主体和多主体的界限,在某种程度上来说是很模糊的,并不是场景中有多个主体需要..

观林望实的博客 3362

Java并发编程新纪元:探索Executor线程池框架

在Java并发编程领域,线程的创建与管理至关重要。传统通过new Thread()的方式在性能优化、资源高效利用及系统扩展性方面存在明显局限。鉴于此,本文将介绍Executor线程池框架,这一相较于传统线程创建方式更为优越的并发编程工具。Executor线程池框架通过复用线程、智能管理资源及灵活配置,显著提升了系统性能、优化了资源利用率,并增强了系统的可扩展性。

Rye的博客 2647

MIPI D-PHY TX 一致性测试实例解析 Part 01 续

本文为MIPI D-PHY TX一致性测试实例解析part01章节的第二部分

一只豌豆象的博客 6041

华为OD机试真题 新系统2026-04-01 Python&JS 实现【空间占用计算】

员工A的磁盘空间经常被耗尽,他需要找到占用空间最大的目录或文件,然后决定如何清理文件释放空间。给定某一目录,请编写程序帮助他统计该目录内一级子目录和文件的占用空间,并返回目标目录一级子项(文件或子目录)中占用空间最大的项。

MISAYAONE的博客 1298

Java线程池——Executor框架

这个类适当地扩展了AbstractQueuedSynchronizer,以简化获取和释放围绕每个任务执行的锁。这可以防止中断,这些中断旨在唤醒等待任务的工作线程,而不是中断正在运行的任务。我们实现了一个简单的不可重入互斥锁,而不是使用ReentrantLock,因为我们不希望工作任务在调用setCorePoolSize等池控制方法时能够重新获得锁。此外,为了在线程实际开始运行任务之前抑制中断,我们将锁状态初始化为负值,并在启动时(在runWorker中)清除它。

qq_25046827的博客 2379

Windows10下安装VMware16虚拟机

由于本人系统为Windows 10 家庭中文版,无法安装Linux子系统WSL,虽然网上也有强制安装的方法,但为保险起见,还是把之前的VMware虚拟机重新进行安装,并浅浅记录一下安装过程。

沉香best的博客 861

Java 多线程与线程池 Thread弊端与Executor存在问题 及解决方法

文章目录Java 多线程与线程池 Thread弊端与Executor存在问题 及解决方法1. 使用Thread弊端2. 线程池背景及优势3. Executor解析3.1 线程池原理3.2 配置线程池3.3 优雅关闭线程池4. Executor存在问题解决方法5. Ref Java 多线程与线程池 Thread弊端与Executor存在问题 及解决方法 1. 使用Thread弊端 new Threa...

小鹅鹅的博客 6075

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合ollama无限token实现7*24小时工作(附配置)

2026最新openclaw(clawbot/moltbot)真正在自己个人电脑上搭建部署,配置飞书远程远程让AI助理操控电脑完成任务,以及结合 ollama 无限token实现7*24小时工作,以及部署安装需要的 skills 完成复杂的工作任务(附完整可以运行的配置文件)。 很多人已经会配置安装 openclaw 了 ,但是 安装完成之后真正让电脑自动运行起来的很好,完成出色工作的更少,最常见的就是聊聊天,或者执行一些简单的命令,理解要让电脑自动化工作,openclaw、skills、大模型这三样。

代码讲故事 2961

【unity】【WebRTC】从0开始创建一个Unity远程媒体流app-构建可同步场景

本文介绍了如何利用Unity和WebRTC技术实现远程画面传输。通过配置Render Streaming组件、设置信令管理器和视频流发送器,构建了一个可同步的Unity场景。文中详细说明了从场景搭建到浏览器端测试的完整流程,并提供了常见问题排查方法。该方案适用于远程调试、云游戏、VR共享等场景,具有低延迟、高兼容性等特点。文章还包含项目源码下载链接,方便读者实践操作。最终实现了Unity端到浏览器端的实时画面传输,为后续实现双向互动奠定了基础。

每日出拳老爷子的博客 1840

Java基础之Executor框架&线程池介绍

在现代计算机系统中,程序的执行通常需要多个任务同时进行,尤其是在多核处理器的环境下,高效地利用计算资源变得尤为重要。Java 提供了丰富的并发工具,而Executor框架正是其中专门用于管理和优化线程执行的核心组件。它不仅简化了线程的创建和管理,还提供了一种更为灵活和高效的方式来处理并发任务。Executor 是 Java 并发包()提供的任务执行框架,旨在解耦任务提交与执行,提高线程管理的灵活性,避免手动创建和销毁线程的高昂开销。它提供了一套标准化的线程池实现,用于任务调度、线程复用和负载管理。

道可道非常道 1494

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

《Java线程池》Executor 以及Executors

《Java线程池》Executor 以及Executors线程池的相关类的体系结构如下:先看Executor接口,是最根上的接口 public interface Executor { /* * Executes the given command at some time in the future. The command * may

wojiushimogui的博客 1450

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深度学习工具包 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")

java中Executor线程池讲解与实例

近期研究了一下java自带的线程池工具Executo,所以记录一下学习的内容。什么是线程池? 线程池是预先创建线程的一种技术。线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中。这些线程都是处于睡眠状态,即均为启动,不消耗CPU,而只是占用较小的内存空间。当请求到来之后,缓冲池给这次请求分配一个空闲线程,把请求传入此线程中运行,进行处理。当预先创建的线程都处于运行状态,

witness_mei的博客 2574

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java多线程 线程池Executor框架

Java多线程 Executor框架

Yeats_Liao的博客 3843

Java线程池之Executor框架、四种常见的线程池

1. Executor框架简介 ① Java任务调度的两级调度模型 在HotSpot VM的线程模型中,Java线程(java.lang.Thread)被一对一的映射为本地操作系统线程:Java线程启动时会创建一个本地操作系统线程;该Java线程终止时,本地操作系统线程也会被回收。操作系统会调度所有线程并把他们分配给可用的CPU。 Java任务调度的两级调度模型: 在上层,应用程序的被分解为...

lucyLee的博客 1747

Executor的介绍及线程池的应用

1、Executor Executor的相关关系图 Executors少了一个创建线程池的方法newScheduledThreadPool() 继承和实现关系 public interface ExecutorService extends Executor {} public abstract class AbstractExecutorService implements ExecutorService {} public interface ScheduledExecutorServ

安余生的博客 4609

Java 入门指南:Java 并发编程 —— Executor、Executors 构建线程池

Executor 是 Java 并发编程中的一个接口,用于执行异步任务。它定义了一组方法来提交任务并执行它们,以及管理任务的执行状态和结果。 Executor 接口允许将任务提交给执行器,它将负责在后台线程中运行任务并返回结果(如果有)。执行器封装了线程池,可自动管理线程的创建、调度和销毁,从而提供了一种方便的方式来管理并发任务。

热带鱼的技术博客 1918

《Java线程池》:Executor生命周期

《Java线程池》:Executor生命周期我们知道线程是有多种执行状态的,同样管理线程的线程池也有多种状态。JVM会在所有线程(非后台daemon线程)全部终止后才退出,为了节省资源和有效释放资源关闭一个线程池就显得很重要。有时候无法正确的关闭线程池,将会阻止JVM的结束。线程池Executor是异步的执行任务,因此任何时刻不能够直接获取提交的任务的状态。这些任务有可能已经完成,也有可能正在执行或

wojiushimogui的博客 5482

Java 线程池的使用【一】【Executor】

当一个程序中若需要创建大量线程,并在任务结束后销毁,会给系统带来过渡的消耗资源以及过渡切换线程的危险,从而可能导致系统崩溃。 线程和数据库连接,这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是线程池。 线程池主要有两个作用: 控制线程数量(提高线程的可管理性) 重用线程(提高响应速度,降低资源消耗) Java里线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具,真正的线

单枪匹码 1120

Java进阶篇之线程池(Executor框架)深度解析

Executor框架的设计目的是将任务的提交与执行分离,它通过Executor接口定义了执行任务的基本行为,而接口则提供了更丰富的功能,包括任务的提交、关闭执行器和等待所有任务完成的能力。这一框架的核心组件包括和。Executor框架,特别是线程池,是Java多线程编程中不可或缺的一部分。它不仅简化了线程管理,还提升了程序的性能和响应性。通过合理配置线程池的参数,开发者可以优化多线程应用,实现资源的有效利用。理解和掌握Executor框架的使用,对于构建高效、稳定的并发应用具有重要意义。

小码农的博客 1172
上一篇: 13个Redis面试题,你都知道哪些?
下一篇: 你了解Java中的并发编程吗?
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值