Java 线程池

浅谈Java线程池,Java线程池解析。 掌握线程池是后端程序员的基本要求,相信大家求职面试过程中,几乎都会被问到有关于线程池的问题。我在网上搜集了几道经典的线程池面试题,并以此为切入点,谈谈我对线程池的理解。如果有哪里理解不正确,非常希望大家指出,接下来大家一起分析学习吧。 阅读详情

为什么要使用线程池:目前的大多数网络服务器,包括Web服务器、Email服务器以及数据库服务器等都具有一个共同点,就是单位时间内必须处理数目巨大的连接请求,但处理时间却相对较短。 传统多线程方案中我们采用的服务器模型则是一旦接受到请求之后,即创建一个新的线程,由该线程执行任务。任务执行完毕后,线程退出,这就是是“即时创建, 即时销毁”的策略。尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数极其频繁,那么服务器将处 于不停的创建线程,销毁线程的状态

线程池:是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务

线程池底层分析:复用机制,使用BlockingQueue阻塞队列缓存线程。为什么使用阻塞队列,因为其他线程执行时需要时间的,在其他线程执行的时候,新线程需要等待,但是不能丢失,缓存到阻塞队列里。阻塞队列通过阻塞可以保留住当前想要继续入队的任务。当队列中没有线程的时候,去阻塞队列中去拿,会被阻塞,直到队列中有新的线程。

java中的线程池是通过Executor框架实现的,Executor 框架包括类:Executor,Executors,ExecutorService,ThreadPoolExecutor ,Callable和Future,FutureTask等。

线程池的优点:

1,可以减少线程的创建和销毁的开销,性能佳。

2,提高响应的时间,当任务到达的时候(当前线程池中已经存在线程)任务可以不需要线程创建,就能执行。

3,统一分配和销毁,有规则的对创建的线程进行管理。

线程池的缺点:

在不适合的场合下可能会比不使用线程池消耗更多的资源。

Executor: 所有线程池的接口,只有一个方法。Executor用于执行提交的Runnable任务。Executor提供了每个线程如何运行,线程的具体使用调度机制的解耦的一种方式。一般用Executor执行线程,而不是显示地创建线程

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

ExecutorService: 增加Executor的行为,是Executor实现类的最直接接口。

Executors: 提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService 接口。

线程池的分类以及创建:

有四种线程池:可缓存的,定长的,定时的,单例的。

四种线程池的创建都是对ThreadPoolExecutor的构造的包装。

ThreadPoolExecutor(int corePoolSize,  
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,  
                              BlockingQueue<Runnable> workQueue)

  1. corePoolSize  核心线程数,实际运行线程数
  2. maximumPoolSize最大线程数,最多可以创建多少线程。
  3. keepAliveTime (非核心线程)闲置线程最大存活时间。
  4. unit 超时时间的单位     有七种取值   (TimeUnit.DAYS;               //天
                                                                  TimeUnit.HOURS;             //小时
                                                                  TimeUnit.MINUTES;           //分钟
                                                                  TimeUnit.SECONDS;           //秒
                                                                  TimeUnit.MILLISECONDS;      //毫秒
                                                                  TimeUnit.MICROSECONDS;      //微妙
                                                                  TimeUnit.NANOSECONDS;       //纳秒)
  5. BlockingQueue  阻塞队列,是java.util.concurrent下的主要用来控制线程同步的工具。如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒。同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间才会被唤醒继续操作。
  6.   RejectedExecutionHandler handler   超出 maximumPoolSizes + workQueue 时,任务会交给RejectedExecutionHandler来处理

Executors.newCachedThreadPool();   创建一个无界的可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

Executors.newFixedThreadPool(int nThreads)创建一个固定大小的线程池,控制线程最大并发数,超出的线程会在队列中等待

Executors.newScheduledThreadPool(int corePoolSize)创建一个定长线程池,支持定时及周期性任务执行。

Executors.newSingleThreadExecutor() 创建一个单线程的后台线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行

newCachedThreadPool

public class CacheThreadPool {
    public static void main(String[] args) {
		ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

		for (int i = 0; i < 100; i++) {
			final int count = i;
			cachedThreadPool.execute(new Runnable() {
				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName() + ": i = " + count );
				}
			});
		}
		
		
	}
}

执行的结果显示:并不是申请要创建100个线程,就会执行100个线程。会有线程会进行缓存,然后进行复用。

可缓存的线程池:他是一个‘伪无界线程池’

  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

他创建了一个核心线程为0,可创建最大线程数为整型量最大值,当非核心线程60秒之内没有需要处理的线程,则被回收。

此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。SynchronousQueue是一个是缓冲区为1的阻塞队列(同步移交)。

要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待接收这个元素。因此即便SynchronousQueue一开始为空且大小为1,第一个任务也无法放入其中,因为没有线程在等待从SynchronousQueue中取走元素。因此第一个任务到达时便会创建一个新线程执行该任务。

使用情况:对于大量短暂异步任务的程序来说,使用该线程池能够大大提高性能 。但是对于耗时的任务,阻塞队列长度为1,他的最大线程数是Integer.MAX_VALUE,所以当大量任务呗提交以后,会一直创建新的线程,消耗更多的资源。

newFixedThreadPool

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

这是一个定长的线程池,构造的时候,传入参数,该参数即是核心线程数,也是最大线程数,并且空闲线程永远都不会被回收,他的阻塞队列是一个LinkedBlockingQueue,队列长度是整型量的最大值。所以该线程池可控制线程最大并发数。

newScheduledThreadPool

  public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    } 

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

参数与上边定长线程池一致,但是缓存队列他用的是DelayedWorkQueue,这是一个变长的队列,初始长度为16,每次增加自己的一半(newCapacity = oldCapacity + (oldCapacity >> 1)))是一个无界队列,它能按一定的顺序对工作队列中的元素进行排列。

特点:指定延时后执行任务。周期性重复执行任务。

  ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
	  executor.scheduleAtFixedRate(new Runnable() {
		
		@Override
		public void run() {
			System.out.println("输出" + System.currentTimeMillis());
		}
	}, 0, 4, TimeUnit.SECONDS);

该线程是表明,创建3个个核心线程,并且提交的线程按照,0表示第一次执行时的延迟时间,4表示每经过4秒执行一次任务(指定延迟时间。重复执行);并且提交多个线程的时候,按一定的顺序执行。

newSingleThreadExecutor

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

LinkedBlockingQueue<Runnable>()也是一个"伪无界队列"。

这是一个单例的线程池,核心线程数和最大线程数都为1,也就是说,该线程池最大的并发量就是1,使用唯一的线程来保证所有请求都是按照先进先出的顺序来执行的。在线程执行的过程中,如果发生为异常,线程结束,会产生新的线程来执行后续的任务。并且在线程结束当前任务之后可以重用,而不会销毁。(在这里单例的线程池和我们普通的线程十分相似,而什么时候该起一个Thread,什么时候该使用单例的线程池呢。1,当线程所要执行的任务已经确定 2,线程不需要频繁的创建和销毁 3, 线程不需要被复用的时候,可以使用Thread)

RejectedExecutionHandler (拒绝策略)

线程池中的拒绝策略有四种:拒绝策略是在(有界)队列满了,并且实际运行线程数大于最大可创建线程数时,线程池拒绝执行任务时的策略。

AbortPolicy  (中止策略) 默认策略:表示拒绝执行,抛出异常

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }

DiscardPolicy(抛弃策略):表示如果现在已经超过了最大线程数,则抛弃新提交的任务。而不做任何其他的事

 public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }

DiscardOldestPolicy(丢弃最老的):该策略表示,抛弃最老的哪个线程,也就是队列的头部的线程,腾出位置,将新提交的线程加到队列。

 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }

CallerRunsPolicy(调用者线程去执行):该策略表示,如果现在线程池已经不能执行时,该任务将由调用者线程去执行。

  public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }

 

 

 

手把手教你用TI MOSFET搭建0-100mA恒流源电路(附避坑指南) 本文详细介绍了如何使用TI MOSFET SI1204D搭建0-100mA恒流源电路,包括基础原理、电路设计、PCB布局和热管理技巧。通过分步指导和避坑指南,帮助工程师实现高精度、低成本的电流控制方案,适用于LED驱动、传感器激励等多种应用场景。 阅读详情

相关推荐

华为使用MicroG安装并使用Google服务教程

鉴于众多华为手机用户因无法使用Google服务而感到不便,我经过多次摸索和测试,总结了一份简单易懂的教程,希望能够帮助到大家。无论是需要使用Google Play商店下载应用,还是需要使用Google服务进行工作和学习,本文将详细介绍如何在华为手机上安装并使用Google服务。二、前置条件软件要求:Aurora Store(替代Google Play商店)、MicroG Companion、MicroG Server(替代Google框架)

weixin_41926602的博客 3万+

spring 的线程池还是 java 的线程池

Java 提供了一个强大的并发库,其中包含了线程池的基本实现。线程池是接口的实现类,用于管理线程的创建、执行和终止。通过线程池,开发者可以避免频繁创建和销毁线程带来的开销,从而提升应用程序的性能。Spring 框架对 Java 的并发库进行了封装,使得线程池的配置更加简洁和灵活。Spring 提供了接口,这是对 JavaExecutor接口的扩展,允许开发者更容易地配置和管理线程池。Spring 的线程池配置通常通过 XML 或 Java 配置类来实现,并且 Spring 提供了多种实现,如等。

Flying_Fish_roe的博客 1674

C# 进程间 双内存共享 高帧率图像传输

演示了两个进程之间通过 双内存共享 的方式, 来实时处理图像,并以高帧率(40~60FPS)传输的基本示例。 进程间内存共享的优点:高性能、低延迟、资源效率高、简单可靠。 适用场景:实时图像处理、大数据传输、多进程协作、实时监控系统,等等。

qianqiansd 1996

Java 线程池

在实际使用中,线程是很占用系统资源的,如果对线程管理不善很容易导致系统问题。(1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中依次执行。(1)线程池中最多执行1个线程,之后提交的线程活动将会排在队列中依次执行。(2)线程池中的线程可进行缓存重复利用和回收。(1)线程池中的线程处于一定的量,可以很好的控制线程的并发量。(2)线程可以重复被使用,在显式关闭之前,都将一直存在。(1)线程池中具有指定数量的线程,即便是空线程也将保留。(3)当线程池中,没有可用线程,会重新创建一个线程。

ggfgfggg的博客 1065

Intel Realsense windows安装与入门

realsense400系列介绍: https://www.intelrealsense.com/stereo-depth/?utm_source=intelcom_website&utm_medium=button&utm_campaign=day-to-day&utm_content=D400_learn-more_button realsense 435i介绍: ...

hanshuning的专栏 1万+

【中文OCR】中文字符图片的分割方法

最近想做一个关于中文OCR的小系列,也是对之前做的东西的一个总结。作为这个系列的第一篇,我觉得还是有必要说一下关于中文字符图片分割的问题。因为现在开源的OCR代码比较多,相对而言对字符图片的分割的方法提的比较少,尤其是中文字符图片的分割还是有一定困难在里面的。 一、普遍使用的切割方法 现在大部分开源项目上用切割方法还是基于水平、垂直投影字符切割方法。 原理比较简单容易理解,也比较容易实现。先...

zhangzm0128 1万+

java的线程池及动态线程池

Java 线程池(Thread Pool)是 Java 并发编程中的重要组件,主要用于管理和复用线程,以提高程序的并发性能、减少线程创建和销毁的开销,并防止资源耗尽。Java 提供了 包下的 框架来管理线程池。在高并发环境下,如果每个任务都创建一个新线程:Java 提供了 框架来管理线程池,其中主要的类包括: 是 Java 线程池的核心实现类,其构造方法如下: 3.1 参数解析: (核心线程数)(最大线程数) & (非核心线程存活时间 & 时间单位)(任务队列)(线程工厂)(拒绝策略)任

Hard_pea的博客 2262

ESP32连接PDM麦克风操作指南:新手入门必看

手把手教你如何将ESP32与PDM麦克风连接,采集音频数据并用于音频分类应用。内容涵盖硬件接线、代码配置及实际调试技巧,适合初学者快速上手esp32在声音识别场景中的使用。

weixin_42590539的博客 1329

Java 线程池详解

Java线程池是一个管理线程的工具,它能够显著提高多线程程序的性能和可管理性。线程池是Java中用于管理和控制一组线程的机制,它可以有效地减少创建和销毁线程的开销,提高系统性能。线程池通过重复使用已存在的线程来执行新的任务,避免了频繁地创建和销毁线程所带来的资源消耗。优势特点降低资源消耗:避免过度创建线程导致的系统开销。提升响应速度:可以快速分配线程来执行任务,提高程序响应效率。增强可管理性:提供统一管理线程的手段,方便监控和调优。Executor。

weixin_42093668的博客 2070

Android14 SystemUI如何实现下拉菜单栏高斯模糊背景效果(类似于毛玻璃效果)

我们都知道,从Android12起,下拉菜单栏控制中心都是黑色的,看起来非常不美观,而且国内的手机系统UI都做的比较美观,大部分的下拉菜单UI背景都是实现了高斯模糊效果,所以客户也会要求实现类似于这样的效果。在以前的Android项目中,实现下拉菜单栏的模糊背景就是通过截图的方式进行替换背景,而这种方式下拉菜单背景极易替换不了,就算是在各个地方都适配,还是有概率在复杂场景或者一些测试手法下出现背景是黑的情况,并且这种方式还比较影响性能,毕竟每次都要去截图一次,多做了额外的事。

热衷于Android Framework和系统APP的修改经验分享 1793

【智能车Code review】——小S与中S道路判断

基本思想: 找到中线的左拐点和右拐点,并且计算出两点之间的空间距离。通过限制空间距离,分为中S和小S。 注意这种情况:当20行以下的中线斜率比较陡,此时可以通过人为限制设定,将第0行的中线设置为拐点。 if (flag_centre_right_point == 0 && flag_centre_left_point == 1 && parameterB >= 0.5 && centre_left_point[0] >= 33) { .

hanhan的博客 6104

Java线程池原理及四种线程池的使用

Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执

honghailiang的专栏 1万+

YOLOv11改进 - C3k2融合 | C3k2融合融合WDBB宽度多样分支模块(Width Diverse Branch Block)通过多尺度分支增强特征表征能力

本文着眼于灰度图像目标检测所面临的挑战,提出了增强型目标检测网络 YOLO - MIF,该网络整合了多种多信息融合策略以对 YOLOv8 网络进行改进。文章开篇介绍了一种可创建伪多通道灰度图像的技术,此技术能增加网络的通道信息,同时缓解潜在的图像噪声与虚焦模糊问题。随后运用网络结构重新参数化技术,在不增加推断时间的情况下提升网络的检测性能。此外,引入了一种新颖的解耦式检测头,增强了模型处理灰度图像时的表现能力。

魔改工程师的博客 770

java线程池

ThreadPoolExecutor自定义参数。在Java并发编程中,线程池是管理线程资源的。自定义参数,避免资源耗尽风险。以下是几种常见线程池(通过。:在复杂生产系统中,

yuren_xia的博客 934

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

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

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

Java线程池

Java线程池 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线...

weixin_41924879的博客 1189

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java 线程池及线程池状态

Java 线程池及线程池状态

qq_41956014的博客 1万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

java线程池之java自带的四种线程池

使用ThreadPoolExecutor创建线程池比较麻烦,对于很多人来说不易使用,所以java已经帮我们设计好了四种线程池。查看java源代码发现这四种线程池仍然是由ThreadPoolExecutor创建的,只不过把相关的参数已经设计好了而已。 案例一:同时演示三种线程池 /* * 任务类 */ class MyTask implements Runnable { String th

御前两把刀的专栏 1177

java线程池【通过源码角度看java线程池】

在查看源码之前,还是先看下整体的调用流程图,有个直观的感受。线程池提交任务的流程:调用线程池的 execute(Runnable command) 方法提交一个 Runnable 对象。首先,线程池会检查当前活跃线程的数量是否小于 corePoolSize。如果线程数小于 corePoolSize,则会创建一个新的线程来执行提交的 Runnable 任务。如果当前活跃线程数大于或等于 corePoolSize,则会尝试将 Runnable 加入到工作队列(workQueue)中。

m0_50149847的博客 1434

【从0到1学习Java线程池】Java线程池的简介以及使用

这是【从0到1学习Java线程池】系列文章的第 壹 篇,该系列文章总共三篇,介绍了 Java 线程池的使用以及原理,并且最后会实现一个基本的线程池。本篇文章主要介绍了 Java 线程池以及它的使用。

远航 | FIBOS.io 3785

java线程池:线程池怎么开启的、线程池怎么工作的、线程池是怎么关闭的

1.序 位于 java.util.concurrent 下的 ThreadPoolExecutor 是java的线程池,可以用来管理线程。 本文围绕线程池的开启、工作、关闭三个方向进行探究,去追溯源码的实现。 2.线程池怎么开启的 ThreadPoolExecutor 有四个构造方法,如下: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit, B.

Yuwen_forJava的博客 3789

Java线程池使用

我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:   如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。   那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?   在Java中可以通过线程池来达到这样的效果。今天我们就...

Jbase的博客 3203

java线程池都有哪些_java中有哪些常见的线程池

java中有哪些常见的线程池发布时间:2020-11-05 15:18:16来源:亿速云阅读:85作者:Leah这篇文章将为大家详细讲解有关java中有哪些常见的线程池,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。首先我们列出Java 中的六种线程池如下线程池名称描述FixedThreadPool核心线程数与最大线程数相同SingleThreadE...

weixin_35544512的博客 1069

java线程池详解

Executors场景核心线程最大线程队列类型拒绝策略说明CPU 密集CPU 核数核数控制上下文切换IO 密集核数×2核数×2~4有界队列防止内存膨胀高并发高并发数高并发×2快速失败顺序执行11保证顺序定时任务按需设置按需设置使用如果你有具体的业务场景(如消息队列消费、Web接口处理、批量处理等),我可以帮你单独设计一个更合理的线程池配置,想要吗?

2301_79652490的博客 854
上一篇: Java 内部类(成员内部类)
下一篇: Java8 Lambda表达式
Embra_ce
博客等级 码龄9年 2粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值