Collections提供的同步包装方法

news2025/1/11 23:48:04

Java同步容器类是通过synchronized(内置锁)来实现同步的容器,比如Vector、 HashTable以及SynchronizedList等容器。 线程安全的同步容器类主要有: Vector、 Stack、 HashTable等。

Collections提供的同步包装方法

Java提供一组包装方法,将一个普通的基础容器包装成一个线程安全的同步容器。例如通过Collections.synchronizedSortedSet 包装方法能将一个普通的SortedSet容器包装成一个线程安全的SortedSet同步容器。除了提供了对SortedSet进行同步包装的方法之外, java.util.Collections还提供了一系列的对其他的基础容器进行同步包装的方法,如synchronizedList()方法将基础List包装成线程安全的列表容器, synchronizedMap()方法将基础Map容器包装成线程安全的容器, synchronizedCollection()方法将基础Collection容器包装成线程安全的Collection容器。

//创建一下基础的有序集合
SortedSet<String> elementSet = new TreeSet<String>();
//增加元素
elementSet.add("element 1");
elementSet.add("element 2");
//将elementSet包装成一个同步容器
SortedSet sorset = Collections.synchronizedSortedSet(elementSet);

同步容器面临的问题

可以通过查看Vector、 HashTable、 java.util.Collections同步包装内部类的源码,发现这些同步容器的实现线程安全的方式是:在需要同步访问的方法上加上关键字synchronized。synchronized在线程没有发生争用的场景下处于偏向锁的状态,其性能是非常高的。但是,一旦发生了线程争用, synchronized会由偏向锁膨胀成重量级锁,在抢占和释放时发生CPU内核态与用户态切换,所以削弱了并发性,降低了吞吐量,而且会严重影响性能。

JUC高并发容器

JUC高并发容器是基于非阻塞算法(或者无锁编程算法)实现的容器类,无锁编程算法主要通过CAS(Compare And Swap) +Volatile组合实现,通过CAS保障操作的原子性,通过volatile保障变量的内存可见性。无锁编程算法的主要优点如下:

  • 开销较小:不需要在内核态和用户态之间切换进程。
  • 读写不互斥:只有写操作需要使用基于CAS机制的乐观锁,读读操作之间可以不用互斥。

List—CopyOnWriteArrayList

JUC包中高并发List主要有CopyOnWriteArrayList,对应的基础容器为ArrayList。CopyOnWriteArrayList相当于线程安全的ArrayList,它实现了List接口。在读多写少的场景中,其性能远远高于ArrayList的同步包装容器。在很多应用场景中,读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据,因此如果每次读取都进行加锁操作其实是一种资源浪费。我们应该允许多个线程同时访问List的内部数据,毕竟读操作是线程安全的。

**原理:**CopyOnWrite(写时复制)就是在修改器对一块内存进行修改时,不直接在原有内存块上进行写操作,而是将内存复制一份,在新的内存中进行写操作,写完之后,再将原来的指针(或者引用)指向新的内存,原来的内存被回收。 CopyOnWriteArrayList是写时复制思想的一种典型实现:其含有一个指向操作内存的内部指针array,而可变操作(add、 set等)是在array数组的副本上进行的。当元素需要被修改或者增加时,并不直接在array指向的原有数组上操作,而是首先对array进行一次复制,将修改的内容写入复制的副本中。写完之后,再将内部指针array指向新的副本,这样就可以确保修改操作不会影响访问器的读取操作了。 CopyOnWriteArrayList的原理如图7-2所示。从名字可以看出: CopyOnWriteArrayList是一个满足CopyOnWrite思想并使用Array数组存储数据的线程安全List。

在这里插入图片描述

CopyOnWriteArrayList的写入操作add()方法在执行时加了独占锁以确保只能有一个线程进行写入操作,避免多线程写的时候会复制出多个副本。 当add()操作完成后, array的引用就已经指向另一个存储空间了。 既然每次添加元素的时候都会重新复制一份新的数组,那就带来了一个问题,就是增加了内存的开销,如果容器的写操作比较频繁,那么其开销就比较大。所以,在实际应用的时候, CopyOnWriteArrayList并不适合进行添加操作。但是在并发场景下,迭代操作比较频繁, CopyOnWriteArrayList就是一个不错的选择。

CopyOnWriteArrayList有一个显著的优点,那就是读取、遍历操作不需要同步,速度会非常快。所以, CopyOnWriteArrayList适用于读操作多、写操作相对较少的场景(读多写少),比如可以在进行“黑名单”拦截时使用CopyOnWriteArrayList。

CopyOnWriteArrayList和ReentrantReadWriteLock读写锁的思想非常类似,即读读共享、写写互斥、读写互斥、写读互斥。但是前者相比后者更进一步:为了将读取的性能发挥到极致, CopyOnWriteArrayList读取是完全不用加锁的,而且写入也不会阻塞读取操作,只有写入和写入之间需要进行同步等待,于是读操作的性能得到大幅度提升。

弱一致性

数据一致性就是读到最新更新的数据:

  • 强一致性:当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值

  • 弱一致性:系统并不保证进程或者线程的访问都会返回最新的更新过的值,也不会承诺多久之后可以读到。Thread-0 读到了脏数据,不一定弱一致性就不好,并发高和一致性是矛盾的,需要权衡。

在这里插入图片描述

在 java.util 包的集合类就都是快速失败的,而 java.util.concurrent 包下的类都是安全失败。安全失败:采用安全失败机制的集合容器,在迭代器遍历时直接在原集合数组内容上访问,但其他线程的增删改都会新建数组进行修改,就算修改了集合底层的数组容器,迭代器依然引用着以前的数组(快照思想),所以不会出现异常

Set

JUC包中Set主要有CopyOnWriteArraySet、 ConcurrentSkipListSet。

  • CopyOnWriteArraySet继承于AbstractSet类,对应的基础容器为HashSet。
  • ConcurrentSkipListSet是线程安全的有序集合,对应的基础容器为TreeSet。

Map

JUC包中Map主要有ConcurrentHashMap和ConcurrentSkipListMap。

  • ConcurrentHashMap对应的基础容器为HashMap。 JDK 6中的ConcurrentHashMap采用一种更加细粒度的“分段锁”加锁机制, JDK 8中采用CAS无锁算法。
  • ConcurrentSkipListMap对应的基础容器为TreeMap。其内部的Skip List(跳表)结构是一种可以代替平衡树的数据结构,默认是按照Key值升序的。
ConcurrentHashMap

ConcurrentHashMap是一个常用的高并发容器类,也是一种线程安全的哈希表。 Java 7以及之前版本中的ConcurrentHashMap使用Segment(分段锁)技术将数据分成一段一段存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。 Java 8对其内部的存储结构进行了优化,使之在性能上有了更进一步的提升。

ConcurrentHashMap和同步容器HashTable的主要区别在锁的类型和粒度上: HashTable实现同步是利用synchronized关键字进行锁定的,其实是针对整张哈希表进行锁定的,即每次锁住整张表让线程独占,虽然解决了线程安全问题,但是造成了巨大的资源浪费。

HashMap 和 HashTable 的区别
  • 基础容器HashMap是线程不安全的,HashTable线程安全。
  • HashTable不允许key和value为null。
  • HashTable使用synchronized来保证线程安全,包含get()/put()在内的所有相关需要进行同步执行的方法都加上了synchronized关键字,以锁定这个哈希表。
JDK 1.7 版本 ConcurrentHashMap 的组合结构

ConcurrentHashMap的内部结构的层次关系为ConcurrentHashMap→Segment→HashEntry。这样设计的好处在于,每次访问的时候只需要将一个Segment锁定,而不需要将整个Map类型集合都进行锁定。
在这里插入图片描述

JDK 1.7中的ConcurrentHashMap采用了Segment分段锁的方式实现。一个ConcurrentHashMap中包含一个Segment数组,一个Segment中包含一个HashEntry数组,每个元素是一个链表结构(一个哈希表的桶)。

HashEntry结构用于存储“ Key-Value对”(即“键-值对”)数据,以及存储了其后驱节点的指针。

在这里插入图片描述

Segment在ConcurrentHashMap中扮演锁的角色,每个Segment守护着一个HashEntry数组中的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。 ConcurrentHashMap中的一个段称为Segment, Segment继承了ReentrantLock,所以一个段又是一个ReentrantLock。 Segment内部拥有一个HashEntry数组类型的成员table,数组中的每个元素又是一个链表,这个由HashEntry链接起来的链表对应于一个哈希表的桶,也就是说, table的一个元素对应于哈希表的一个桶。 ConcurrentHashMap在默认并发级别时会创建包含16个Segment对象的数组。

在这里插入图片描述

在ConcurrentHashMap中,哈希时如果产生“碰撞”,将采用“分离链接法”来处理:把“碰撞”的HashEntry对象链接成一个链表,形成一个桶。由于HashEntry的next字段为final型,因此新节点只能在链表的表头处插入。 在一个空桶中依次插入A、 B、 C三个HashEntry对象后的结构图如图7-14所示

JDK 1.8 版本 ConcurrentHashMap 的结构

在JDK 1.8中, ConcurrentHashMap已经抛弃了Segment分段锁机制,存储结构采用数组+链表或者红黑树的组合方式,利用CAS+Synchronized来保证并发更新的安全。 JDK 1.7的ConcurrentHashMap为了进行并发热点的分离,默认情况下将一个table分裂成16个小的table(Segment表示),从而在Segment维度进行比较细粒度的并发控制。实际上,如果并发线程多,这种粒度还是没有足够细。所以, JDK 1.8的ConcurrentHashMap将并发控制的粒度进一步细化,也就是进一步进行并发热点的分离,将并发粒度细化到每一个桶。既然如此,比较粗粒度的Segment已经没有存在的必要,每一个桶已经变化成实质意义的Segment,所以该结构直接被丢弃。

JDK 1.8引入了红黑树的结构,当桶的节点数(链表长度)超过一定的阈值(默认为64)时, JDK 1.8将链表结构自动转换成红黑树的结构,可以理解为将链式桶转换成树状桶。 JDK 1.8的ConcurrentHashMap引入了红黑树的原因是:链表查询的时间复杂度为O(n),红黑树查询的时间复杂度为O(log(n)),所以在节点比较多的情况下,使用红黑树可以大大提升性能。

链式桶是一个由NODE节点组成的链表。树状桶是一棵由TreeNode节点组成的红黑树,树的根节点为TreeBin类型。当数据链表(链式桶)长度大于8时且桶的个数超过64时,会转换为TreeBin(树状桶)。 TreeBin作为根节点,可以认为是红黑树对象。在ConcurrentHashMap的table“数组”中,存放就是TreeBin对象,而不是TreeNode对象。

在这里插入图片描述

JDK 1.8版本的ConcurrentHashMap中通过一个Node<K,V>[]数组table来保存添加到哈希表中的桶,而在同一个Bucket位置是通过链表和红黑树的形式来保存的。

在这里插入图片描述

当原有的红黑树内数量小于6时,将红黑树转换成链表。 链表长度大于8 ,链式桶转成红黑树桶。 在这里插入图片描述

树化,当 table.length < 64 时,先尝试扩容,超过 64 时,并且 Treebin.length > 8 时,会将链表树化,树化过程会用 synchronized 锁住链表头。

  1. put,如果该 bin(桶) 尚未创建,只需要使用 cas 创建 bin;如果已经有了,使用synchronized内置锁 锁住链表头进行后续 put 操作,元素添加至 bin 的尾部

  2. get,无锁操作仅需要保证可见性,扩容过程中 get 操作拿到的是 ForwardingNode 会让 get 操作在新 table 进行搜索

  3. 扩容,扩容时以 bin 为单位进行,需要对 bin 进行 synchronized,但这时其它竞争线程也不是无事可做,它们会帮助把其它 bin 进行扩容

  4. ConcurrentHashMap、HashMap 的初始容量为 16,两种 Map 扩容是当前容量翻倍:capacity * 2

总结:第一次添加元素时,默认初期长度为16,当往table中继续添加元素时,通过哈希值跟数组长度取余来决定放在数组的哪个Bucket位置,如果出现放在同一个位置时,就优先以链表的形式存放,在同一个位置的个数又达到了8个以上,如果数组的长度还小于64时,就会扩容数组。如果数组的长度大于等于64,就会将该节点的链表转换成树。 什么时候扩容?当前容量超过阈值,也就是链表中元素个数超过默认设置(8个)时,如果数组table的大小还未超过64,此时就进行数组的扩容,如果超过就将链表转化成红黑树。

扩容机制:

  • 当链表中元素个数超过 8 个,数组的大小还未超过 64 时,此时进行数组的扩容,如果超过则将链表转化成红黑树
  • put 数据后调用 addCount() 方法,判断当前哈希表的容量超过阈值 sizeCtl,超过进行扩容
  • 增删改线程发现其他线程正在扩容,帮其扩容

尽管对同一个Map操作的线程争用会非常激烈,但是在同一个桶内 的线程争用通常不会很激烈,所以使用CAS自旋(简单轻量级锁)、 synchronized偏向锁或轻量级锁不会降低ConcurrentHashMap的性能。为什么不用ReentrantLock显式锁呢?如果为每一个桶都创建一个ReentrantLock实例,就会带来大量的内存消耗。

Queue

JUC包中Queue的实现类包括三类:单向队列、双向队列和阻塞队列。

使用循环 CAS 算法实现非阻塞队列:

  • ConcurrentLinkedQueue是一个基于列表实现的单向无界线程安全队列,按照FIFO(先进先出)原则对元素进行排序。新元素从队列尾部插入,而获取队列元素则需要从队列头部获。ConcurrentLinkedQueu由 head 节点和 tail 节点组成,每个节点由节点元素和指向下一个节点的引用组成,组成一张链表结构的队列。
  • ConcurrentLinkedDeque是基于链表的双向队列,但是该队列不允许null元素。作为双端队列, ConcurrentLinkedDeque可以当作“栈”来使用,并且高效地支持并发环境

除了提供普通的单向、双向队列, JUC拓展了队列,增加了可阻塞的插入和获取等操作,提供了一组加锁实现的阻塞队列,具体如下:

  • ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列。
  • LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列。
  • PriorityBlockingQueue:按优先级排序的队列。
  • DelayQueue: 按照元素的Delay时间进行排序的队列。
  • SynchronousQueue:无缓冲等待队列。

BlockingQueue

在多线程环境中,通过BlockingQueue(阻塞队列)可以很容易地实现多线程之间数据共享和通信,比如在经典的“生产者-消费者”模型中,通过BlockingQueue可以完成一个高性能的实现版本。阻塞队列与普通队列( ArrayDeque等)之间的最大不同点在于阻塞队列提供了阻塞式的添加和删除方法。

ArrayBlockingQueue

ArrayBlockingQueue是一个常用的阻塞队列,是基于数组实现的,其内部使用一个定长数组存储元素。除了一个定长数组外, ArrayBlockingQueue内部还保存着两个整型变量,分别标识队列的头部和尾部在数组中的位置。 通过ReentrantLock类型的成员lock控制添加线程与删除线程的并发访问。 ArrayBlockingQueue的添加和删除操作都是共用同一个锁对象,由此意味着添加和删除无法并行运行,这一点不同于LinkedBlockingQueue。

为什么ArrayBlockingQueue比LinkedBlockingQueue更加常用?前者在添加或删除元素时不会产生或销毁任何额外的Node(节点)实例,而后者会生成一个额外的Node实例。在长时间、高并发处理大批量数据的场景中, LinkedBlockingQueue产生的额外Node实例会加大系统的GC压力。

ArrayBlockingQueue中的元素访问存在公平访问与非公平访问的两种方式,所以ArrayBlockingQueue可以分别作为公平队列和非公平队列使用:

1)对于公平队列,被阻塞的线程可以按照阻塞的先后顺序访问队列,即先阻塞的线程先访问队列。

2)对于非公平队列,当队列可用时,阻塞的线程将进入争夺访问资源的竞争中,也就是说谁先抢到谁就执行,没有固定的先后顺序。

//默认非公平阻塞队列
ArrayBlockingQueue queue = new ArrayBlockingQueue(capacity);
//公平阻塞队列
ArrayBlockingQueue queue1 = new ArrayBlockingQueue(capacity, true);

LinkedBlockingQueue

LinkedBlockingQueue是基于链表的阻塞队列,其内部也维持着一个数据缓冲队列(该队列由一个链表构成)对于添加和删除元素分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

在新建一个LinkedBlockingQueue对象时,若没有指定其容量大小,则LinkedBlockingQueue会默认一个类似无限大小的容量( Integer.MAX_VALUE),这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。

DelayQueue

DelayQueue中的元素只有当其指定的延迟时间到了,才能从队列中获取到该元素。 DelayQueue是一个没有大小限制的队列,因此往队列中添加数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。

PriorityBlockingQueue

基于优先级的阻塞队列和DelayQueue类似, PriorityBlockingQueue并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。在使用的时候要特别注意,生产者生产数据的速度绝对不能快于消费者消费数据的速度,否则时间一长,会最终耗尽所有的可用堆内存空间。

SynchronousQueue

一种无缓冲的等待队列类似于无中介的直接交易,有点像原始社会中的生产者和消费者,生产者拿着商品去集市销售给商品的最终消费者,而消费者必须亲自去集市找到所要商品的直接生产者,如果一方没有找到合适的目标,那么大家都在集市等待。相对于有缓冲的阻塞队列(如LinkedBlockingQueue)来说, SynchronousQueue少了中间缓冲区(如仓库)的环节。

反过来说,又因为仓库的引入,使得商品从生产者到消费者中间增加了额外的交易环节,单个商品的及时响应性能可能会降低,所以对单个消息的响应要求高的场景可以使用SynchronousQueue。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VTK Java项目构建和运行

date: 2019-04-02 10:24:00 VTK Java项目构建和运行 准备工作 本文的运行环境是Ubuntu。在自己建立的VTK build的文件夹&#xff08;这里名称为VTK-bin&#xff0c;见前文&#xff09;&#xff0c;找到vtk.jar&#xff0c;这里在VTK-bin/lib下。 新建工程 使用JetBrains的I…

【图】概念、存储结构、广度优先遍历遍历、深度优先遍历 - 详解

目录 前言 一、图 1.1、基本概念 二、图的存储结构 2.1、存储结构 2.1、邻接矩阵&#xff08;考察重点&#xff09; 2.1.1、代码实现 2.2、邻接表 2.3.1、无向邻接表存储 2.3.2、有向图邻接表存储 3.1、图的广度优先遍历&#xff08;层序遍历&#xff09; 3.2、图的…

Wails + Go 实现图形化桌面应用

效果展示 编写一个热点查看程序&#xff0c;包含百度热搜、微博热搜、头条、知乎等&#xff0c;废话不说上效果图&#xff1a; 效果图1&#xff1a; 效果图2 打包大小 涉及技术点 Golang 使用golang 1.9 编写代码 Wails vue3 使用Wails技术实现GUI渲染&#xff0c;页…

网络——网络协议总结

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。 个人主页&#xff1a;小李会科技的…

笔记本安装CentOS

目标: 1.利用闲置笔记本 2.省电/提高利用率/不安装图形桌面/最小化安装/附加选项:开发工具 step1&#xff1a;镜像下载 CentOS-7.9 163镜像 阿里云镜像 清华大学镜像 随便选一个 step2: 下载U盘系统盘制作工具Rufus U盘写入镜像/安装 step3: 安装完毕进入系统 …

2023年上半年软考学习总结(超详细)

目录 前言 一、背景1.1上次考试感受&#xff1a;1.2这次考试感受&#xff1a;1.3方法&#xff1a; 二、 过程2.1计算机网络概论计算机组成数据表示相关知识校验码相关知识计算机体系结构网络体系结构OSI/RM和TCP/IP计算机安全性可靠性性能评价 2.2 程序设计语言基础知识编译和解…

如何在华为OD机试中获得满分?Java实现【求最小公倍数】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

【Unity3D】广告牌特效

1 前言 广告牌特效是指&#xff1a;空间中的一个 2D 对象始终&#xff08;或尽可能&#xff09;面向相机&#xff0c;使得用户能够尽可能看清楚该 2D 物体。广告牌特效一共有以下 3 种&#xff1a; 正视广告牌&#xff1a;广告牌始终以正视图姿态面向相机&#xff0c;即广告牌…

异常检测进阶梳理1:Tabular AD视角

接触异常检测领域也有一年多的时间了&#xff0c;过程中遇到不少坑&#xff0c;知识体系也在不断更新完善&#xff0c;这里以专题的形式进行知识体系的梳理~ 异常检测&#xff08;Anomaly Detection, AD&#xff09;领域内的划分体系较多&#xff0c;这里基于异常检测最常用到的…

【P39】JMeter 随机顺序控制器(Random Order Controller)

文章目录 一、随机顺序控制器&#xff08;Random Order Controller&#xff09;参数说明二、测试计划设计2.1、测试计划一2.2、测试计划二 一、随机顺序控制器&#xff08;Random Order Controller&#xff09;参数说明 可以让控制器内部的组件按随机顺序执行&#xff08;内部…

Alibaba Arthas学习与使用

Alibaba Arthas学习与使用 目录 下载安装卸载退出快捷键重点部分: 命令 dashboardthreadjvmsyspropsysenvvmoptiongetstaticognlscsmjadmcredefinedumpclassloadermonitorwatchtracestackttoptionsprofiler 下载安装 # 下载 curl -O https://alibaba.github.io/arthas/art…

Apache Kafka - 如何实现可靠的数据传递

文章目录 可靠的数据传递导图 可靠的数据传递 Kafka 通过以下几个方面实现可靠的数据传递: 分区副本 - Kafka 的分区有多个副本,如果某个副本失效,其他副本可以继续服务。生产者重试 - 生产者在发送消息失败时会自动重试,一直到成功发送或者达到最大重试次数。批量确认 - 生产…

云服务器和专用服务器之间的区别

在当今数字化时代&#xff0c;服务器是构建和支持各种应用和服务的基础设施之一。随着技术的发展和需求的增加&#xff0c;出现了不同类型的服务器&#xff0c;其中最常见的是云服务器和专用服务器。本文将详细介绍云服务器和专用服务器之间的区别&#xff0c;以帮助您更好地了…

SpringSecurity从入门到实战

SpringSecurity从入门到实战 0. 简介 ​ Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有…

【LAMP架构】

目录 一、LAMP架构1、组件作用 二、编译安装Apache httpd服务2、安装环境依赖包3、配置软件模块4、编译及安装5、优化配置文件路径&#xff0c;并把httpd服务的可执行程序文件放入路径环境变量的目录中便于系统识别6.添加httpd系统服务7.修改httpd 服务配置文件8.浏览器访问验证…

【云原生|探索 Kubernetes 系列 5】简化 Kubernetes 的部署,深入解析其工作流程

前言 大家好&#xff0c;我是秋意零。 在前面 4 个章节中&#xff0c;我们充分了解了容器技术和 Kubernes 原生时代引擎的架构和设计思想&#xff0c;今天分享的主要内容是&#xff0c;探索 Kubernetes 部署&#xff0c;深入解析其工作流程 &#x1f47f; 简介 &#x1f3e0…

[元带你学: eMMC协议详解 11] Data transfer mode 数据传输模式

依JEDEC eMMC 5.1及经验辛苦整理&#xff0c;付费内容&#xff0c;禁止转载。 所在专栏 《元带你学: eMMC协议详解》 全文2300 字&#xff0c; 主要介绍数据传输模式&#xff0c;本节数据传输模式图非常重要。数据传输模式图可以说是我查对过最频繁的图之一了。eMMC 限定了这么…

数据库基础——6.排序与分页

这篇文章来讲一下数据库的排序与分页 目录 1.排序数据 1.1排序规则 1.2 单列排序 1.3 多列排序 2.分页 2.1 背景 2.2 实现规则 2.3 拓展 1.排序数据 1.1排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&#xff09;&#xff1a;升序 &#xff1b; DESC&a…

怎么一键保存浏览器中打开的所有标签页?

2023年5月28日&#xff0c;周日晚上&#xff1a; 被这个问题困扰很久了&#xff0c;之前一直不知道怎么全部保存浏览器中打开的所有标签页&#xff0c;浪费了不少的时间&#xff0c;今天下午偶然发现了解决办法。 很简单&#xff0c;直接在浏览器里使用快捷键“CtrlShiftD” …

本周大新闻|传Meta与Magic Leap谈专利授权;PS VR2前6周出货60万台

本周XR大新闻&#xff0c;AR方面&#xff0c;苹果XR项目核心高管曝光&#xff1b;传Meta与Magic Leap洽谈专利授权合作&#xff1b;歌尔光学公布新一代AR显示模组&#xff1b;Lumus公布二代波导Z-Lens最新细节&#xff1b;JBD X-cube发布全彩Micro LED光机Hummingbird&#xff…