面试笔记——多线程使用场景
线程池使用场景(CountDownLatch, Future)
CountDownLatch
CountDownLatch(闭锁/倒计时锁)用来进行线程同步协作,等待所有线程完成倒计时(一个或者多个线程,等待其他多个线程完成某件事情之后才能执行)。
- 构造参数用来初始化等待计数值
- await() 用来等待计数归零
- countDown() 用来让计数减一
上图中,给定初始值count = 3,调用await方法来判断count是否为0,若不为0,则将线程挂起等待,当count等于0之后,该线程才能继续执行。T2,T3,T4执行时,它们都调用了countdown(),每一次调用这个方法,都会对count减一。因此,调用了3次之后,T1线程继续执行。
CountDownLatch的使用demo:
import java.util.concurrent.CountDownLatch;public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {//初始化了一个倒计时锁 参数为 3CountDownLatch latch = new CountDownLatch(3);new Thread(() -> {System.out.println(Thread.currentThread().getName()+"-begin...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}//count--latch.countDown();System.out.println(Thread.currentThread().getName()+"-end..." +latch.getCount());}).start();new Thread(() -> {System.out.println(Thread.currentThread().getName()+"-begin...");try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}//count--latch.countDown();System.out.println(Thread.currentThread().getName()+"-end..." +latch.getCount());}).start();new Thread(() -> {System.out.println(Thread.currentThread().getName()+"-begin...");try {Thread.sleep(1500);} catch (InterruptedException e) {throw new RuntimeException(e);}//count--latch.countDown();System.out.println(Thread.currentThread().getName()+"-end..." +latch.getCount());}).start();String name = Thread.currentThread().getName();System.out.println(name + "-waiting...");//等待其他线程完成latch.await();System.out.println(name + "-wait end...");}}
运行结果:
Thread-0-begin...
Thread-1-begin...
main-waiting...
Thread-2-begin...
Thread-0-end...2
Thread-2-end...1
Thread-1-end...0
main-wait end...
使用场景一——批量导入:
项目上线之前,需要把数据库中的数据一次性的同步到es索引库中,数据可能有1000万左右,一次性读取数据肯定不行(oom异常),可以使用线程池的方式导入,利用CountDownLatch来控制,就能避免一次性加载过多,防止内存溢出:
使用场景二——数据汇总:
在一个电商网站中,用户下单之后,需要查询数据,数据包含了三部分:订单信息、包含的商品、物流信息;这三块信息都在不同的微服务中进行实现的,可以通过线程池实现,提升查询效率:
在实际开发的过程中,难免需要调用多个接口来汇总数据,如果所有接口(或部分接口)的没有依赖关系,就可以使用线程池+future来提升性能。
使用场景三——异步线程:
在很多软件中,都提供了搜索功能,并且会记录用户的搜索记录。在实现搜索功能的时候,不能让搜索功能受到保存搜索记录的影响,通常采取异步的方式来保存搜索记录,通过异步线程来实现该功能。当用户输入关键字开始搜索后,正常返回用户搜索的相关数据,再开一个线程来记录用户的历史记录,并把这个新开的线程放到线程池中去执行。
控制方法允许并发访问的线程数量
Semaphore 信号量,是JUC包下的一个工具类,底层是AQS,我们可以通过其限制执行的线程数量。
使用场景:通常用于那些资源有明确访问数量限制的场景,常用于限流 。
Semaphore使用步骤
- 创建Semaphore对象,可以给一个容量
- semaphore.acquire(): 请求一个信号量,这时候的信号量个数-1(一旦没有可使用的信号量,也即信号量个数变为负数时,再次请求的时候就会阻塞,直到其他线程释放了信号量)
- semaphore.release():释放一个信号量,此时信号量个数+1
import java.util.concurrent.Semaphore;public class SemaphoreCase {public static void main(String[] args) {// 1. 创建 semaphore 对象Semaphore semaphore = new Semaphore(3);// 2. 10个线程同时运行for (int i = 0; i < 10; i++) {new Thread(() -> {try {// 3. 获取许可,计数-1semaphore.acquire();} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println("running...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end...");} finally {// 4. 释放许可 计数+1semaphore.release();}}).start();}}}
对ThreadLocal的理解
ThreadLocal是多线程中对于解决线程安全的一个操作类,它会为每个线程都分配一个独立的线程副本从而解决了变量并发访问冲突的问题。ThreadLocal 同时实现了线程内的资源共享。
ThreadLocal基本使用:
- set(value) 设置值——ThreadLocal 自己作为 key,资源对象作为 value,放入当前线程的 ThreadLocalMap 集合中
- get() 获取值——以 ThreadLocal 自己作为 key,到当前线程中查找关联的资源值
- remove() 清除值——以 ThreadLocal 自己作为 key,移除当前线程关联的资源值
demo:
public class ThreadLocalTest {static ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {new Thread(() -> {String name = Thread.currentThread().getName();threadLocal.set("value1");print(name);System.out.println(name + "-after remove : " + threadLocal.get());}, "t1").start();new Thread(() -> {String name = Thread.currentThread().getName();threadLocal.set("value2");print(name);System.out.println(name + "-after remove : " + threadLocal.get());}, "t2").start();}static void print(String str) {//打印当前线程中本地内存中本地变量的值System.out.println(str + " :" + threadLocal.get());//清除本地内存中的本地变量threadLocal.remove();}}
输出:
t1 :value1
t1-after remove : null
t2 :value2
t2-after remove : null
ThreadLocal本质来说就是一个线程内部存储类,从而让多个线程只操作自己内部的值,从而实现线程数据隔离。
set方法:
get方法/remove方法:
ThreadLocal——内存泄漏
Java对象中的四种引用类型:强引用、软引用、弱引用、虚引用
- 强引用:最为普通的引用方式,表示一个对象处于有用且必须的状态,如果一个对象具有强引用,则GC并不会回收它。即便堆中内存不足了,宁可出现OOM,也不会对其进行回收。
- User user = new User();
- 弱引用:表示一个对象处于可能有用且非必须的状态。在GC线程扫描内存区域时,一旦发现弱引用,就会回收到弱引用相关联的对象。对于弱引用的回收,无关内存区域是否足够,一旦发现则会被回收
User user = new User(); WeakReference weakReference = new WeakReference(user);
每一个Thread维护一个ThreadLocalMap,在ThreadLocalMap中的Entry对象继承了WeakReference。其中key为使用弱引用的ThreadLocal实例,value为线程变量的副本(强引用):
static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}
}
避免ThreaLocal内存泄漏——通过remove方法主动释放key、value。
相关文章:

面试笔记——多线程使用场景
线程池使用场景(CountDownLatch, Future) CountDownLatch CountDownLatch(闭锁/倒计时锁)用来进行线程同步协作,等待所有线程完成倒计时(一个或者多个线程,等待其他多个线程完成某件…...

02.0 基于Verilog控制LED灯每秒钟闪烁一次
本段代码是为Verilog初学者提供的一个名为led_blink简单实例Verilog模块,其功能是控制6个LED灯同步闪烁,每秒钟闪烁一次。 本例代码用于理解时序逻辑的概念,理解多个always模块完全并行执行的概念,讲授时可以与C语言的执行过程进行…...

C语言创建文件夹和多级目录
C调用系统命令创建多级目录 #include <stdio.h> #include <stdlib.h>int main() {const char *path "a/b/c";// 创建目录命令的字符串char mkdir_command[100];sprintf(mkdir_command, "mkdir %s", path);// 调用系统命令system(mkdir_comma…...

2024.5.6
#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//设置窗口大小this->resize(1000,740);//设置窗口图标this->setWindowIcon(QIcon("C:\\Users\\Administrator\\Desktop\\pictrue\\Plants.png"));//设置窗口标题this-…...

mybatis配置获取自增主键
mybatis配置获取自增主键 【/n】 01 使用场景 当需要刚刚插入数据库的数据对应的新增主键时,通过配置xml文件,使数据库返回新增主键id,并把主键id与类参数对应 02 涉及配置 注解TableId(type IdType.AUTO):在类主键id通过配…...

完整、免费的把pdf转word文档
在线工具网 https://www.orcc.online 支持pdf转word,免费、完整、快捷 登录网站 https://orcc.online 选择需要转换的pdf文件: 等待转换完成 点击蓝色文件即可下载 无限制,完整转换。...

使用 Lua 协程模拟 Golang 的 go defer 编程模式
封装 go 函数 在 使用 Lua 协程处理异步回调函数 中已经介绍 这里简要列下: 封装 go 函数---go 函数创建并启动一个协程 ---param _co_task function 函数原型 fun(_co:thread) function go(_co_task)local co coroutine.create(_co_task) -- 创建的协程是暂停的…...

网络通信协议,UDP和TCP,初步了解
UDP(User Datagram Protocol)和TCP(Transmission Control Protocol)是两种常见的网络通信协议,用于在计算机网络中进行数据传输。 1. TCP:Transmission Control Protocol(传输控制协议…...

Golang | Leetcode Golang题解之第61题旋转链表
题目: 题解: func rotateRight(head *ListNode, k int) *ListNode {if k 0 || head nil || head.Next nil {return head}n : 1iter : headfor iter.Next ! nil {iter iter.Nextn}add : n - k%nif add n {return head}iter.Next headfor add > …...

美业SaaS系统多门店收银系统源码-【分润常见问题】讲解(一)
美业管理系统源码 博弈美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 促销活动 PC管理后台、手机APP、iPad APP、微信小程序 ▶ 分润常见问题: 1、分润金额基数 所有分润计算的基数均为平台订单中各个商…...

Chatbot 在教育中的应用
Chatbot 在教育中的应用 基本信息 这篇博客主要介绍几篇Chatbot在教育领域中应用的文章,根据文章的侧重点不同,分为介绍教育理论,与介绍系统设计两类。从问题定义、技术方法、教育学理论、实验设计、结论证据几个方面概括各篇文章。 博…...

Apache和Nginx的区别以及如何选择
近来遇到一些客户需要lnmp环境的虚拟主机,但是Hostease这边的虚拟主机都是基于Apache的,尽管二者是不同的服务器软件,但是大多数情况下,通过适当的配置和调整两者程序也是可以兼容的。 目前市面上有许多Web服务器软件,…...

深入探索Element-UI:构建高效Web前端的利器
深入探索Element-UI:构建高效Web前端的利器 引言:前端框架的选择与Element-UI的定位一、Element-UI初探二、快速上手:安装与配置三、核心组件深度解析四、实用功能与进阶技巧五、性能优化与最佳实践六、实战案例分析七、与其他技术栈的集成 安…...
在Ubuntu 24.04 LTS (Noble Numbat)上安装nfs server以及nfs client
在Ubuntu 24.04 LTS (Noble Numbat)上,我使用的是最小化安装, 当然server版本的Ubuntu在安装的时候可能会有网络不通的问题,解决办法见如下文章: ubuntu 24.04 server 仅NAT模式上网设置静态IP设置-CSDN博客文章浏览阅读489次,点赞9次,收藏3次。在Ubuntu 24.04 上设置网…...

供应链|经典论文解读:(s,S) 策略在动态库存下的最优性
文章考虑了具有订购成本(由单位成本加上重新订购成本组成)的动态库存问题。具体而言,对于每个时期,系统在中期开始是做出一系列采购决策——这些采购有助于库存的积累,并在随后的周期被需求所消耗。每时期系统会产生各…...

Python从0到100(二十):文件读写和文件操作
一、文件的打开和关闭 有了文件系统可以非常方便的通过文件来读写数据;在Python中要实现文件操作是非常简单的。我们可以使用Python内置的open函数来打开文件,在使用open函数时,我们可以通过函数的参数指定文件名、操作模式和字符编码等信息…...

AI+客服行业落地应用
一、客服行业变迁 1.传统客服时代 (1)客服工作重复性高,技术含量低 (2)呼出效率低,客服水平参差不齐 (3)管理难度高,情绪不稳定 (4)服务质量…...

40 生产者消费者模型
生产者消费者模型 概念 为何要使用生产者消费者模型,这个是用过一个容器解决生产者和消费的强耦合问题。生产者和消费者之间不需要通讯,通过阻塞队列通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列…...

QT5之windowswidget_菜单栏+工具栏_核心控件_浮动窗口_模态对话框_标准对话框/文本对话框
菜单栏工具栏 新建工程基类是QMainWindow 1、 2、 3、 点.pro文件,添加配置 因为之后用到lambda; 在.pro文件添加配置c11 CONFIG c11 #不能加分号 添加头文件 #include <QMenuBar>//菜单栏的头文件 主窗口代码mainwindow.cpp文件 #include &q…...

Satellite, Aerial, and Underwater Communication Track(WCSP2023)
1.Dispersion Curve Extraction and Source Localization for Single Hydrophone by Combining Image Skeleton Extraction with Advanced Time-Frequency Analysis(图像骨架提取与先进时频分析相结合的单水听器色散曲线提取和源定位) 摘要:时频分析(TF…...

AtCoder Regular Contest 176(ARC176)A、B
题目:AtCoder Regular Contest 176 - tasks 官方题解:AtCoder Regular Contest 176 - editorial 参考:atcoder regular 176 (ARC176) A、B题解 A - 01 Matrix Again 题意 给一个nn的方格,给出m个坐标(x,y)m,在方格中…...

VTK —— 二、教程六 - 为模型加入3D微件(按下i键隐藏或显示)(附完整源码)
代码效果 本代码编译运行均在如下链接文章生成的库执行成功,若无VTK库则请先参考如下链接编译vtk源码: VTK —— 一、Windows10下编译VTK源码,并用Vs2017代码测试(附编译流程、附编译好的库、vtk测试源码) 教程描述 本…...

一种基于图搜索的全局/局部路径避障策略
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一种基于图搜索的全局/局部路径避障策略前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长! 本文先对一种基于图搜索…...

LT2611UX四端口 LVDS转 HDMI2.0,带音频
描述LT2611UX 是一款面向机顶盒、DVD 应用的高性能 LVDS 至 HDMI2.0 转换器。LVDS输入可配置为单端口、双端口或四端口,具有1个高速时钟通道和3~4个高速数据通道,工作速率最高为1.2Gbps/通道,可支持高达19.2Gbps的总带宽。LT2611UX 支持灵活的…...

TypeError报错处理
哈喽,大家好,我是木头左! 一、Python中的TypeError简介 这个错误通常表示在方法调用时,参数类型不正确,或者在对字符串进行格式化操作时,提供的变量与预期不符。 二、错误的源头:字符串格式化…...

PHP的数组练习实验
实 验 目 的 掌握索引和关联数组,以及下标和元素概念; 掌握数组创建、初始化,以及元素添加、删除、修改操作; 掌握foreach作用、语法、执行过程和使用; 能应用数组输出表格和数据。 任务1:使用一维索引数…...

P3743 小鸟的设备
原题链接:小鸟的设备 - 洛谷 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 浮点数二分答案。 首先特判,如果接通设备每秒生成的能量p大于等于所有设备每秒消耗的能量(a[1]a[2]..a[n])直接输出-1&…...

数字旅游以科技创新为动力:推动旅游服务的智能化、网络化和个性化发展,满足游客日益增长的多元化、个性化需求
目录 一、引言 二、科技创新推动旅游服务智能化发展 1、智能化技术的引入与应用 2、智能化提升旅游服务效率与质量 三、科技创新推动旅游服务网络化发展 1、网络化平台的构建与运营 2、网络化拓宽旅游服务渠道与范围 四、科技创新推动旅游服务个性化发展 1、个性化需求…...

64位的IP地址设想
现有的IP地址 IPv4有32位,不够用了。 IPv6有128位,相当多。 实际上,23385亿,只要在IPv4的基础上,加1比特就够用了,IPv6有些太长了。 64位的IP地址 这是个设想。 64位分成七段,8888881664&…...

1.python爬虫爬取视频网站的视频可下载的源url
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、爬取的源网站二、实现代码总结 一、爬取的源网站 http://www.lzizy9.com/ 在这里以电影片栏下的动作片为例来爬取。 可以看到视频有多页,因此需要…...