当前位置: 首页 > article >正文

java多线程下

ThreadLocal

ThreadLocal 有什么用?通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢?JDK 中自带的ThreadLocal类正是为了解决这样的问题。 ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLocal变量名的由来。他们可以使用 get() 和 set() 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
再举个简单的例子:两个人去宝屋收集宝物,这两个共用一个袋子的话肯定会产生争执,但是给他们两个人每个人分配一个袋子的话就不会出现这样的问题。如果把这两个人比作线程的话,那么 ThreadLocal 就是用来避免这两个线程竞争的。

线程池

池化技术想必大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。线程池提供了一种限制和管理资源(包括执行一个任务)的方式。 每个线程池还维护一些基本统计信息,例如已完成任务的数量。

使用线程池的好处:

降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

如何创建线程池?

方式一:通过ThreadPoolExecutor构造函数来创建(推荐)。

线程池常见的参数有哪些

ThreadPoolExecutor 3 个最重要的参数:
corePoolSize : 任务队列未达到队列容量时,最大可以同时运行的线程数量。
maximumPoolSize : 任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
workQueue: 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。ThreadPoolExecutor其他常见参数 :
keepAliveTime:线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁;
unit : keepAliveTime 参数的时间单位。
threadFactory :executor 创建新线程的时候会用到。
handler :饱和策略。关于饱和策略下面单独介绍一下。

线程池处理任务的流程

在这里插入图片描述
如果当前运行的线程数小于核心线程数,那么就会新建一个线程来执行任务。如果当前运行的线程数等于或大于核心线程数,但是小于最大线程数,那么就把该任务放入到任务队列里等待执行。如果向任务队列投放任务失败(任务队列已经满了),但是当前运行的线程数是小于最大线程数的,就新建一个线程来执行任务。如果当前运行的线程数已经等同于最大线程数了,新建线程将会使当前运行的线程超出最大线程数,那么当前任务会被拒绝,饱和策略会调用RejectedExecutionHandler.rejectedExecution()方法。# 如何给线程池命名?

Future

Future 类是异步思想的典型运用,主要用在一些需要执行耗时任务的场景,避免程序一直原地等待耗时任务执行完成,执行效率太低。具体来说是这样的:当我们执行某一耗时的任务时,可以将这个耗时任务交给一个子线程去异步执行,同时我们可以干点其他事情,不用傻傻等待耗时任务执行完成。等我们的事情干完后,我们再通过 Future 类获取到耗时任务的执行结果。这样一来,程序的执行效率就明显提高了。这其实就是多线程中经典的 Future 模式,你可以将其看作是一种设计模式,核心思想是异步调用,主要用在多线程领域,并非 Java 语言独有。
在 Java 中,Future 类只是一个泛型接口,位于 java.util.concurrent 包下,其中定义了 5 个方法,主要包括下面这 4 个功能:
取消任务;
判断任务是否被取消;
判断任务是否已经执行完成;
获取任务执行结果。

AQS

AQS 的全称为 AbstractQueuedSynchronizer ,翻译过来的意思就是抽象队列同步器。这个类在 java.util.concurrent.locks 包下面。

AQS 的原理是什么?

AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
CLH(Craig,Landin,and Hagersten) 队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点(Node)来实现锁的分配。在 CLH 同步队列中,一个节点表示一个线程,它保存着线程的引用(thread)、 当前节点在队列中的状态(waitStatus)、前驱节点(prev)、后继节点(next)。
在这里插入图片描述


http://www.kler.cn/news/17574.html

相关文章:

  • 数据结构(六)—— 二叉树(6)二叉搜索树
  • 【redis】spring-cache使用指南
  • 给孩子描述非对称加密算法
  • 代码随想录算法训练营第三十天 | 航班问题、二维回溯
  • HashMap底层结构和源码分析
  • 爬取景区源码
  • 【Maven笔记1】Maven介绍
  • ConcurrentHashMap底层实现原理
  • Java时间类(四)-- DateTimeFormatter类
  • PostgreSQL 基础知识:psql 入门
  • ChatGPT诞生的新岗位:提示工程师(Prompt Engineer)
  • 发展文旅夜游项目有哪些好处
  • Python实现哈里斯鹰优化算法(HHO)优化随机森林分类模型(RandomForestClassifier算法)项目实战
  • 章节3:02-Apache Commons Collections反序列化漏洞
  • 宝塔windows面板提权获取系统管理员权限方法!(非漏洞BUG)
  • JavaEE阶段测试复习
  • 京东数据分析:2023年Q1白酒电商整体动销增长,中低端酒企压力大
  • 国民技术N32G430开发笔记(14)-IAP升级 usart2接收数据
  • MySQL知识学习03(三大日志详解 binlog、redo log、undo log)
  • Python3 简介
  • Android 9.0 系统systemui下拉通知栏的通知布局相关源码分析
  • 05.rabbitMQ之搭建的各种坑
  • 基于DSP+FPGA+AD9238的冲击波超压测试系统设计与实现
  • 手搓GPT系列之 - chatgpt + langchain 实现一个书本解读机器人
  • Ajax -- from表单与模板引擎
  • 华为OD机试 - 密室逃生游戏(Python)
  • 提示工程玩转 ChatGPT
  • springboot2
  • 【Python】flask
  • SpringBatch之实际操作