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

并发编程之并发容器

目录

并发容器

CopyOnWriteArrayList

应用场景

常用方法

读多写少场景使用CopyOnWriteArrayList举例

  CopyOnWriteArrayList原理

CopyOnWriteArrayList 的缺陷

扩展迭代器fail-fast与fail-safe机制

ConcurrentHashMap

应用场景

常用方法

并发场景下线程安全举例

ConcurrentHashMap底层结构

 ConcurrentSkipListMap

应用场景

常用方法

跳表


并发容器

        java中常用的集合ArrayList、LinkedList、HashMap这些容器都是非线程安全的。Java先提供了同步容器供使用。同步容器可以简单地理解为通过synchronized来实现同步的容器,比如Vector、Hashtable以及SynchronizedList等容器。这样做的代价是削弱了并发性,当多个线程共同竞争容器级的锁时,吞吐量就会降低。

       为了解决同步容器的性能问题,有了并发容器,java.util.concurrent包中提供了多种并发类容器。以下以部分并发容器详细介绍。

CopyOnWriteArrayList

应用场景

1. 读多写少的情况

      当对列表的读操作远远多于写操作时,CopyOnWriteArrayList可以提供良好的性能。由于读操作不涉及锁,多个线程可以同时读取,而写操作只需要在复制时进行同步。

2. 避免读写冲突

       在某些情况下,使用传统的同步容器可能会导致读写冲突,因为读取和写入操作同时进行时可能会引发竞态条件。CopyOnWriteArrayList避免了这种冲突,通过牺牲内存来保证读取的一致性。

3. 不需要实时更新的情况

       如果对实时性要求不高,即时写操作会导致列表被复制,但读取操作仍然可以在原始列表上进行,从而保持一致性。

4. 稳定的数据集

       当数据集相对稳定,且写操作相对较少时,CopyOnWriteArrayList是一个合适的选择。写操作不频繁的情况下,复制列表的开销相对较小。

常用方法
CopyOnWriteArrayList copyOnWriteArrayList= new CopyOnWriteArrayList();
// 新增
copyOnWriteArrayList.add(1);
// 设置(指定下标)
copyOnWriteArrayList.set(0, 2);
// 获取(查询)
copyOnWriteArrayList.get(0);
// 删除
copyOnWriteArrayList.remove(0);
// 清空
copyOnWriteArrayList.clear();
// 是否为空
copyOnWriteArrayList.isEmpty();
// 是否包含
copyOnWriteArrayList.contains(1);
// 获取元素个数
copyOnWriteArrayList.size();
读多写少场景使用CopyOnWriteArrayList举例

       假设有一个任务调度器,其中包含了多个定时任务,每个任务都有一个执行时间。多个线程同时读取任务列表以查看下一个要执行的任务,而写入操作仅在添加、删除任务时发生。 

import java.util.concurrent.CopyOnWriteArrayList;public class TaskScheduler {// 使用CopyOnWriteArrayList作为任务列表private CopyOnWriteArrayList<Task> taskList = new CopyOnWriteArrayList<>();// 添加任务public void addTask(Task task) {taskList.add(task);}// 删除任务public void removeTask(Task task) {taskList.remove(task);}// 获取下一个要执行的任务public Task getNextTask() {if (!taskList.isEmpty()) {// 获取第一个任务(最早执行的任务)return taskList.get(0);}return null;}// 其他与任务调度相关的操作// ...
}class Task {private String name;private long executionTime;// 构造方法、getter、setter等// ...
}
  CopyOnWriteArrayList原理

       CopyOnWriteArrayList 内部使用了一种称为“写时复制”的机制。当需要进行写操作时,它会创建一个新的数组,并将原始数组的内容复制到新数组中,然后进行写操作。因此,读操作不会被写操作阻塞,读操作返回的结果可能不是最新的,但是对于许多应用场景来说,这是可以接受的。此外,由于读操作不需要加锁,因此它可以支持更高的并发度。

            

CopyOnWriteArrayList 的缺陷

1. 内存开销大
       每次写入操作都会创建一个列表的副本,这导致了较大的内存开销。在数据集很大的情况下,频繁的写入操作可能占用大量内存,这可能成为一个问题。
2. 不适合写入频繁的场景
        如果写入操作非常频繁,复制列表的开销可能会变得显著,并且可能会导致性能问题。适用于写多读少或写入相对较少的场景。
3. 不适合实时性要求高的场景
       由于写入操作会导致复制整个列表,而且复制操作不是原子的,因此在写入过程中,读取操作可能会看到部分修改或者不一致的状态。这使得 CopyOnWriteArrayList 不适合对实时性要求很高的场景。
4. 不支持并发修改迭代
       CopyOnWriteArrayList 的迭代器是不可修改的,因此在使用迭代器遍历列表时,不允许修改列表。虽然这是为了确保线程安全设计的,但对于某些应用可能会限制灵活性。
5. 不适用于元素更新频繁的情况
       如果在列表中的元素需要频繁更新,CopyOnWriteArrayList 可能不是最佳选择,因为每次更新都会导致整个列表的复制,开销较大。


扩展迭代器fail-fast与fail-safe机制

fail-fast 机制

       fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生 fail-fast 事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了。那么线程A访问集合时,就会抛出 ConcurrentModificationException异常,产生fail-fast事件。

fail-fast解决方案

方案一

       在遍历过程中所有涉及到改变modCount 值的地方全部加上synchronized 或者直接使用 Collection#synchronizedList,这样就可以解决问题,但是不推荐,因为增删造成的同步锁可能会阻塞遍历操 作。

方案二

       使用CopyOnWriteArrayList 替换 ArrayList,推荐使用该方案(即fail-safe)。

fail-safe机制

       任何对集合结构的修改都会在一个复制的集合上进行,因此不会抛出ConcurrentModificationException。在 java.util.concurrent 包中的集合,如  CopyOnWriteArrayList、ConcurrentHashMap 等,它们的迭代器一般都是采用 Fail-Safe 机制。

缺点

1. 采用 Fail-Safe 机制的集合类都是线程安全的,但是它们无法保证数据的实时一致性,它们只能保证数据的最终 一致性。在迭代过程中,如果集合被修改了,可能读取到的仍然是旧的数据。

2. Fail-Safe 机制还存在另外一个问题,就是内存占用。由于这类集合一般都是通过复制来实现读写分离的,因此它 们会创建出更多的对象,导致占用更多的内存,甚至可能引起频繁的垃圾回收,严重影响性能。


ConcurrentHashMap

        ConcurrentHashMap是Java中线程安全的哈希表,它支持高并发并且能够同时进行读写操作。 在JDK1.8之前,ConcurrentHashMap使用分段锁以在保证线程安全的同时获得更大的效率。JDK1.8开始舍弃了分段锁,使用自旋+CAS+synchronized关键字来实现同步。官方的解释中:一是节省内存空间 ,二是分段锁需要更多的内存空间。

应用场景

1. 高并发的数据存储
       当多个线程需要同时访问和修改一个共享的哈希表时,ConcurrentHashMap 提供了一种线程安全的方式,避免了在读取和写入操作上的锁竞争。
2. 缓存管理
        用作缓存的存储结构,特别是在读多写少的情况下。由于 ConcurrentHashMap 具有分段锁机制,多个线程可以并发地访问不同的段,从而提高并发性能。
3. 并发计数器
        当需要进行多线程并发计数时,可以使用 ConcurrentHashMap 的原子操作方法,如 compute、merge 等,以确保计数的一致性。
4. 分布式系统中的协调
        在分布式系统中,ConcurrentHashMap 可以用于协调不同节点之间的数据共享。它提供了一种线程安全的方式来管理共享数据,以避免并发访问问题。
5. 任务调度和执行管理
       在多线程的任务调度和执行场景中,ConcurrentHashMap 可以用来存储和管理任务的状态、结果等信息,确保在并发情况下的正确性。
6. 实时性要求不高的场景
       相较于传统的 HashMap,ConcurrentHashMap 在保证线程安全的同时,提供了更高的并发性。因此,在对实时性要求不是非常高的场景下,可以使用它来提高并发性能。
7. 在线程池中的任务管理
       当多个线程池中的任务需要共享数据时,ConcurrentHashMap 可以作为一个线程安全的数据结构来确保并发访问的正确性。

常用方法
 // 创建一个 ConcurrentHashMap 对象
ConcurrentHashMap<Object, Object> concurrentHashMap = new ConcurrentHashMap<>();
// 添加键值对
concurrentHashMap.put("key", "value");
// 添加一批键值对
concurrentHashMap.putAll(new HashMap());
// 使用指定的键获取值
concurrentHashMap.get("key");
// 判定是否为空concurrentHashMap.isEmpty();
// 获取已经添加的键值对个数
concurrentHashMap.size();
// 获取已经添加的所有键的集合
concurrentHashMap.keys();
// 获取已经添加的所有值的集合
concurrentHashMap.values();
// 清空
concurrentHashMap.clear();
并发场景下线程安全举例
import java.util.concurrent.ConcurrentHashMap;public class CacheManager {// 使用ConcurrentHashMap作为缓存存储private static ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();public static void main(String[] args) {// 模拟多个线程同时访问缓存for (int i = 0; i < 5; i++) {String key = "Key" + i;Thread readerThread = new Thread(() -> readFromCache(key));readerThread.start();String newKey = "NewKey" + i;String value = "Value" + i;Thread writerThread = new Thread(() -> addToCache(newKey, value));writerThread.start();}}// 从缓存读取数据的方法private static void readFromCache(String key) {// 使用get方法从缓存读取数据String value = cache.get(key);System.out.println(Thread.currentThread().getName() + ": Reading from cache - Key: " + key + ", Value: " + value);}// 向缓存添加数据的方法private static void addToCache(String key, String value) {// 使用put方法向缓存添加数据cache.put(key, value);System.out.println(Thread.currentThread().getName() + ": Adding to cache - Key: " + key + ", Value: " + value);}
}

         在上述案例中,多个线程可以同时读取和写入缓存项,而ConcurrentHashMap会确保在多线程并发访问的情况下不会发生数据不一致或线程安全问题。

ConcurrentHashMap底层结构

在jdk1.7及其以下的版本中,结构是用Segments数组 + HashEntry数组 + 链表实现的。

      

jdk1.8抛弃了Segments分段锁的方案,而是改用了和HashMap一样的结构操作,也就是数组 + 链表 + 红黑树结构,比jdk1.7中的ConcurrentHashMap提高了效率,在并发方面,使用了cas + synchronized的方式保证数据的一致性。

        

链表转化为红黑树需要满足2个条件:

1. 链表的节点数量大于等于树化阈值8

2. Node数组的长度大于等于最小树化容量值64

#树化阈值为8
static final int TREEIFY_THRESHOLD = 8;
#最小树化容量值为64
static final int MIN_TREEIFY_CAPACITY = 64;

 ConcurrentSkipListMap

       ConcurrentSkipListMap 是 Java 中的一种线程安全、基于跳表实现的有序映射(Map)数据结构。 它是对 TreeMap 的并发实现,支持高并发读写操作。 ConcurrentSkipListMap适用于需要高并发性能、支持有序性和区间查询的场景,能够有效地提高系 统的性能和可扩展性。

应用场景

1. 并发映射
       
ConcurrentSkipListMap 实现了 ConcurrentMap 接口,可以被用作并发映射(key-value映射)的数据结构。多个线程可以安全地同时访问和修改映射。
2. 有序性要求
      
 由于底层是基于跳表实现的,ConcurrentSkipListMap 中的元素是有序的。如果你需要按照键的自然顺序或者自定义的比较器顺序来存储和访问数据,这个类就是一个很好的选择。
3. 高并发读写
      
 跳表的结构允许多个线程并发地进行读取和写入操作,而不会导致锁竞争。这使得 ConcurrentSkipListMap 在高并发环境下的读写性能表现相对较好。
4. 范围查询
     
  跳表的结构使得范围查询变得高效。ConcurrentSkipListMap 提供了一些方法,如 subMap,可以用于获取键范围内的子映射。
5. 替代传统的并发映射实现
  
     在某些情况下,ConcurrentSkipListMap 可以作为对传统的基于锁的并发映射实现的一种替代。它的设计允许更高的并发性。

常用方法
添加元素:
put(K key, V value): 将指定的键值对添加到映射中。
putIfAbsent(K key, V value): 如果指定的键尚未与值关联,则将其与给定的值关联。获取元素:
get(Object key): 返回指定键所映射的值,如果该键不存在,则返回 null。
firstKey(): 返回映射中的第一个(最小的)键。
lastKey(): 返回映射中的最后一个(最大的)键。
lowerKey(K key): 返回严格小于给定键的最大键,如果不存在则返回 null。
higherKey(K key): 返回严格大于给定键的最小键,如果不存在则返回 null。删除元素:
remove(Object key): 从映射中删除指定键的映射。
pollFirstEntry(): 移除并返回映射中的第一个(最小的)映射。
pollLastEntry(): 移除并返回映射中的最后一个(最大的)映射。范围查询:
subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive): 返回映射中键的部分视图,其键范围从 fromKey 到 toKey。遍历:
entrySet(): 返回包含映射中所有映射的 Set 视图。
keySet(): 返回包含映射中所有键的 NavigableSet 视图。
values(): 返回包含映射中所有值的 Collection 视图。其他操作:
size(): 返回映射中的键值对数量。
isEmpty(): 如果映射不包含键值对,则返回 true。
clear(): 从映射中移除所有映射。
跳表

跳表是一种基于有序链表的数据结构,支持快速插入、删除、查找操作,其时间复杂度为O(log n), 比普通链表的O(n)更高效。

 跳表的特性

一个跳表结构由很多层数据结构组成。每一层都是一个有序的链表,默认是升序。也可以自定义排序方法。 最底层链表(图中所示Level1)包含了所有的元素。 如果每一个元素出现在LevelN的链表中(N>1),那么这个元素必定在下层链表出现。 每一个节点都包含了两个指针,一个指向同一级链表中的下一个元素,一个指向下一层级别链表中的相同值元素。

跳表的查找

 跳表的插入

跳表插入数据的流程如下:

找到元素适合的插入层级K,这里的K采用随机的方式。若K大于跳表的总层级,那么开辟新的一层,否则在对应 的层级插入。 申请新的节点。 调整对应的指针。 

假设我要插入元素13,原有的层级是3级,假设K=4:

相关文章:

并发编程之并发容器

目录 并发容器 CopyOnWriteArrayList 应用场景 常用方法 读多写少场景使用CopyOnWriteArrayList举例 CopyOnWriteArrayList原理 CopyOnWriteArrayList 的缺陷 扩展迭代器fail-fast与fail-safe机制 ConcurrentHashMap 应用场景 常用方法 并发场景下线程安全举例 Con…...

K8s---存储卷(动态pv和pvc)

当我要发布pvc可以生成pv&#xff0c;还可以共享服务器上直接生成挂载目录。pvc直接绑定pv。 动态pv需要两个组件 1、卷插件&#xff1a;k8s本生支持的动态pv创建不包括nfs&#xff0c;需要声明和安装一个外部插件 Provisioner: 存储分配器。动态创建pv,然后根据pvc的请求自动…...

JS判断对象是否为空对象的几种方法

通过JSON自带的stringify()方法判断 function isEmptyObj(obj) {return JSON.stringify(obj) {} } console.log(对象是否为空&#xff1a;, isEmptyObj({}))for in 循环判断 function isEmptyObj(obj) {for(let item in obj) {return true}return false } console.log(对…...

算法通关村第十五关—用4KB内存寻找重复元素(青铜)

用4KB内存寻找重复元素 用4KB内存寻找重复元素 题目要求&#xff1a;给定一个数组&#xff0c;包含从1到N的整数&#xff0c;N最大为32000&#xff0c;数组可能还有重复值&#xff0c;且N的取值不定&#xff0c;若只有4KB的内存可用&#xff0c;该如何打印数组中所有重复元素。…...

【PHP】判断字符串是否是有效的base64编码

目录 1.检测长度&#xff1a; 2.检查字符集&#xff1a; 3.判断是否能正常解码 在PHP中&#xff0c;判断一个字符串是否是有效的Base64编码&#xff0c;可以通过以下几种方法&#xff1a; 1.检测长度&#xff1a; Base64编码的字符串长度必须是4的倍数&#xff08;对于标准…...

鼎盛合|测量精度SOC芯片开发中的技术问题整理

SOC芯片近几年的发展势头迅猛&#xff0c;许多行业中俱可见其身影。SOC芯片并不是传统意义上的芯片&#xff0c;它是一个由多种功能集成的一个芯片。SOC芯片自身在出厂时便带有部分程序&#xff0c;是为了方便设计开发而针对某些行业设计的特定功能。如芯海的SOC芯片大多数则是…...

sql | 学生参加各科考试次数

学生表: Students------------------------ | Column Name | Type | ------------------------ | student_id | int | | student_name | varchar | ------------------------ 在 SQL 中&#xff0c;主键为 student_id&#xff08;学生ID&#xff09;。 该表内的每…...

uniapp(vue2)+VoerkaI18n多语言

今天我学习了VoerkaI18n国际化插件&#xff0c;它是一个适用于Javascript/Vue/React/Solid/ReactNative的国际化全流程解决方案。VoerkaI18n可以帮助我们轻松地实现应用程序的多语言支持&#xff0c;使得应用程序可以适应不同的语言环境。 比较吸引我的是集成自动翻译,t(“中华…...

C51--测速小车

测速小车&#xff1a; 测速模块&#xff1a; 用途&#xff1a; 广泛用于电机转速检测&#xff0c;脉冲计数&#xff0c;位置限位等。 高低电平&#xff1a; 有遮挡&#xff0c;输出高电平&#xff1b; 无遮挡&#xff0c;输出低电平。 接线&#xff1a; VCC——正极 GND——接…...

ORACLE报错:ORA-04091 表XXX发生了变化,触发器/函数不能读它

ORACLE报错:ORA-04091 表发XXX生了变化&#xff0c;触发器/函数不能读它 问题描述问题分析解决办法拓展&#xff1a;自治事务的特点 问题描述 在开发校验函数FUNCTION的时候&#xff0c;用数据跑批测试的时候报错。经排查这个校验函数FUNCTION的被一个存储过程中的update语句调…...

Arm LDM和STM的寻址方式

A32指令集中包含多数据传输指令LDM和STM&#xff0c;也就是单条指令可以传输多个寄存器的值与内存交互&#xff0c;这对于数据块传输以及寄存器的压入栈很有帮助。LDM和STM指令可分别用于实现堆栈的pop和push操作。对于堆栈操作&#xff0c;基寄存器通常是堆栈指针(SP)。 LDM和…...

网络技术基础入门全套实验-厦门微思网络CCNA实验手册

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; 微思简介&#xff08;https://www.xmws.cn) 微思成立于2002年&#xff0c;是一个诚信敬业、积极向上、充满活力、专注技术服务的企业。 微思获得了八…...

【已解决】C语言实现多线程检索数据

本博文源于笔者正在学习的c语言。学习如何用多线程进行检索数据。这里以检索一个数组的数据为例&#xff0c;给出代码&#xff0c;并分析如何进行线程通信&#xff0c;如果检索到&#xff0c;其余就别检索了。 文章目录 问题来源问题解决方案代码实现效果总结 问题来源 想要用…...

用LM Studio:2分钟在本地免费部署大语言模型,替代ChatGPT

你想在本地使用类似ChatGPT 的大语言模型么&#xff1f;LM Studio 可以帮你2分钟实现ChatGPT的功能&#xff0c;而且可以切换很多不同类型的大语言模型&#xff0c;同时支持在Windows和MAC上的PC端部署。 LM Studio是一款面向开发者的友好工具&#xff0c;特别适合那些想要探索…...

C语言经典算法之直接排序算法

目录 前言 一、代码实现 二、时空复杂度 时间复杂度&#xff1a; 空间复杂度&#xff1a; 前言 建议&#xff1a;1.学习算法最重要的是理解算法的每一步&#xff0c;而不是记住算法。 2.建议读者学习算法的时候&#xff0c;自己手动一步一步地运行算法。 tips:希尔排序算…...

前端开发vscode 常用插件记录

通用插件&#xff1a; 一、live Server 主要作用是提供一个本地开发服务器&#xff0c;以便实时预览和调试网页应用程序。 二、css peek 它的主要作用是帮助开发人员更轻松地查找和导航CSS样式表中的类、ID、选择器和样式定义&#xff08;鼠标移动到css样式名即可查看样式&…...

基于JavaWeb+BS架构+SpringBoot+Vue基于web的多媒体素材管理系统的设计和实现

基于JavaWebBS架构SpringBootVue基于web的多媒体素材管理系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1选题背景与意义 1 1.1 研究背景 1 1.2 研究意义…...

常用的dom操作

常用的dom操作 查找元素&#xff1a;可以使用 getElementById、querySelector、querySelectorAll 等方法来查找元素。创建元素&#xff1a;可以使用 createElement 方法创建新的元素节点。插入元素&#xff1a;可以使用 appendChild、insertBefore 等方法将元素插入到指定位置…...

Hotspot源码解析-第十七章-虚拟机万物创建(三)

17.4 Java堆空间内存分配 分配Java堆内存前&#xff0c;我们先通过两图来了解下C堆、Java堆、内核空间、native本地空间的关系。 1、从图17-1来看&#xff0c;Java堆的分配其实就是从Java进程运行时堆中选中一块内存区域来映射 2、从图17-2&#xff0c;可以看中各内存空间的…...

Spring MVC 的RequestMapping注解

RequestMapping注解 使用说明 作用&#xff1a;用于建立请求URL和处理请求方法之间的对应关系。 出现位置&#xff1a; 类上&#xff1a; 请求 URL的第一级访问目录。此处不写的话&#xff0c;就相当于应用的根目录。写的话需要以/开头。它出现的目的是为了使我们的 URL 可以…...

navicat for oracle

前言 Oracle中的概念并不是创建数据库&#xff0c;而是创建一个表空间&#xff0c;然后再创建一个用户&#xff0c;设置该用户的默认表空间为我们新创建的表空间&#xff0c;这些操作之后&#xff0c;便和你之前用过的mysql数据库创建完数据库一模一样了。 创建数据库 使用O…...

行业分享----dbaplus174期:美团基于Orchestrator的MySQL高可用实践

记录 MySQL高可用方案-MMM、MHA、MGR、PXC https://blog.csdn.net/jycjyc/article/details/119731980 美团数据库高可用架构的演进与设想 https://tech.meituan.com/2017/06/29/database-availability-architecture.html...

springboot集成钉钉通知

目录 1.通过自定义机器人方式发送群消息 1.1说明 1.2发送普通消息示例&#xff08;采用加签方式&#xff09; 1.3注意事项 2.通过企业内部应用发送钉钉消息 2.1说明 2.2示例 2.3注意 1.通过自定义机器人方式发送群消息 1.1说明 官网地址&#xff1a; 自定义机器人发送…...

直播预告丨看零售场,如何玩转 MaaS

今年&#xff0c;有一个被频繁提及的词是MaaS 这类工具正在帮助千行百业实现大模型落地产业 在零售场&#xff0c;特别是像京东这样拥有超高并发、超复杂协同的电商场内 也沉淀出了一套通用的AI基础设施——九数算法中台 从提升客户服务体验、平台效率出发&#xff0c;训练各…...

高创新!EI论文复现+改进:聚合温度调控策略的综合能源系统/微电网/虚拟电厂多目标优化调度程序代码!

程序考虑供热的热惯性&#xff0c;并根据室内供热效果进行柔性供热&#xff0c;发挥热温度负荷的“储能”能力&#xff1b;针对普适性参数的室内空调进行集群研究&#xff0c;深入剖析温度设定值调整导致负荷波动的机理&#xff0c;并提出一种新的温度调整方法&#xff0c;平抑…...

详解Matlab深度学习进行波形分割

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…...

如何在Windows 10/11的防火墙中禁止和允许某个应用程序,这里提供详细步骤

想阻止应用程序访问互联网吗&#xff1f;以下是如何通过简单的步骤阻止和允许Windows防火墙中的程序。​ 一般来说&#xff0c;大多数用户永远不需要担心应用程序访问互联网。然而&#xff0c;在某些情况下&#xff0c;你需要限制应用程序访问互联网。 例如&#xff0c;有问题…...

vivado 添加现有IP文件、生成IP

添加现有IP文件 作为从AMD IP目录添加和自定义IP的替代方案&#xff0c;您可以直接添加XCI或XCIX文件。此过程不同于从按以下方式编目&#xff1a; •XCI或XCIX文件可能是早期版本&#xff0c;也可能是相同或完全自定义的版本AMD IP目录中发现的类似IP。 •XCI或XCIX文件可能…...

C++右值引用,右值引用与const引用的区别

1.右值与左值 左值&#xff1a;可以取地址的、有名字的变量&#xff0c;有持久性&#xff1b;右值&#xff1a;一般是不可寻址的常量&#xff0c;或在表达式求值过程中创建的无名临时对象&#xff0c;短暂性的。 2.右值引用 C11新增了另一种引用——右值引用。这种引用可指向…...

启英泰伦推出「离线自然说」,离线语音交互随意说,不需记忆词条

离线语音识别是指不需要依赖网络&#xff0c;在本地设备实现语音识别的过程&#xff0c;通常以端侧AI语音芯片作为载体来进行数据的采集、计算和决策。但是语音芯片的存储空间有限&#xff0c;通过传统的语音算法技术&#xff0c;最多也只能存储数百条词条&#xff0c;导致用户…...