- 小教板
-
从概念上说
前者(web_concurrent_start)是语句的并发 后者(lr_rendezvous)是user的并发
这是两件完全完全不同的事情 没有什么可以比较的 仅仅只是都有“同时执行”的意思而已
详细来说
URL-based 方式 默认是将每个请求录制成一条语句 而一条语句只建立一个到服务器的连接
比方说 一个page上面 有图片 有文本 有音视频 有编辑框 有按钮 有链接 有复选框 等等等等……
那么请求图片 请求文本 请求音视频…… 就上面所有那些 都各自分别是一条语句
如果不写web_concurrent_start和web_concurrent_end函数 就默认按语句的顺序执行请求
而写了web_concurrent_start和web_concurrent_end函数之后 就会将这些请求同时发送
容易想象的是 并发请求时的压力 会比顺序请求的时候 要大
而集合点 或者也有叫同步点的 它的概念比较容易理解 就不解释了
下面针对你的问题:
“1用户下,使用web_concurrent_start(end)一次性提交20请求;
和20用户下,通过rendezvous来集合后,每用户提交1个请求;
这两种场景应该是一样的,因为都是一次向服务器同时提交了10个请求。”
这是不准确的 原因至少有两点:
第一 单用户多请求的并发性 要强于多用户的集合点
这是因为 集合点是多线程的并发 它的并发性是有限的 宏观上是并发 微观上不可能并发
因为如果你的电脑是单CPU的 那么你就不可能获得严格意义上的并发执行
按照操作系统中 进程和线程的关系 在某一个时间点 严格上讲 就只有一个人得到执行
除非你给每个用户配备一个CPU 才能达到真正的并发 但显然这是不可能的
第二 你的每个请求的开销并不一定是相同的 这也导致测试结果的不可控
最简单的 请求一段文字 与请求一段音视频 产生的系统开销肯定是不一样的
你使用的web_custom_request函数 并不是发送完了就完了 而是返回完毕才算完成
返回一段几KB的文字 与返回一段几MB的音视频 对网络的压力肯定是不一样的
当然还可以有其他的理解 你可以自己继续分析
而且可以预见的是 你这种测试 每一次都有可能获得不同的结果
我指的是你请求的东西不一样的情况下 比如你换一个站点进行测试 结果就有可能是相反的
原因就是我上面说的第二点
concurrent是什么意思
concurrentadj.〈正式〉同时发生的; 同时完成的; 同时存在的; n.[数] 共点; 同时发生的事件; **************************************************************如果你对这个答案有什么疑问,请追问,另外如果你觉得我的回答对你有所帮助,请千万别忘记采纳哟!***************************************************************2023-07-16 15:45:372
concurrent与simultaneous的区别
concurrent [ku0259n"ku028cru0259nt] adj. 并发的;一致的;同时发生的n. 共点;同时发生的事件simultaneous [,simu0259l"teiniu0259s] adj. 同时的;联立的;同时发生的n. 同时译员2023-07-16 15:45:461
ConcurrentHashMap如何实现高效地线程安全?
读的时候用volatile保证可见性,使读到的数据永远是最新的写的时候用分段锁只对部分数据加锁2023-07-16 15:45:542
简单总结ConcurrentHashMap
在并发使用到HashMap的时候,往往不建议直接用HashMap,因为HashMap在并发写数据的时候容易因为rehash的过程产生环形链表的情况。所以在并发使用Map结构时,一般建议使用ConcurrentHashMap。 在JDK1.7中ConcurrentHashMap采用了 数组+Segment+分段锁 的方式实现。 从上面的结构我们可以了解到,ConcurrentHashMap定位一个元素的过程需要进行两次Hash操作。第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部。 JDK8中ConcurrentHashMap参考了JDK8 HashMap的实现,采用了数组+链表+红黑树的实现方式来设计,内部大量采用CAS操作。并发控制使u2f64 synchronized 和 CAS 来操作。 (JDK1.6 以后 对 synchronized 锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在 JDK1.8 中还能看到 Segment 的数据结构,但 是已经简化了属性,只是为了兼容旧版本; JDK1.8的Nod节点中value和next都用volatile修饰,保证并发的可见性。 可以理解为,synchronized 只锁定当前链表或红u2fcau2f06叉树的u2fb8节点,这样只要 hash 不冲突,就不会产u2f63并发,效率u2f1c提升 N 倍。 Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采u2f64 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突u2f7d存在的; Hashtable(同u2f00把锁) :使u2f64 synchronized 来保证线程安全,效率u2fae常低下。当u2f00个线程访问同步u2f45法时,其他线程也访问同步u2f45法,可能会进u2f0a阻塞或轮询状态,如使u2f64 put 添加元素,另u2f00个线程不能使u2f64 put 添加元素,也不能使u2f64get,竞争会越来越激烈效率越低; 总结一下: JavaGuide2023-07-16 15:46:091
concurrentmap为什么线程安全
concurrentmap线程安全原因:1、JDK1.7中,ConcurrentHashMap使用的锁分段技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。2、JDK1.8放弃了锁分段的做法,采用CAS和synchronized方式处理并发。以put操作为例,CAS方式确定key的数组下标,synchronized保证链表节点的同步效果。2023-07-16 15:46:161
HashMap、HashTable、ConcurrentHashMap的原理与区别
从类图中可以看出来在存储结构中ConcurrentHashMap比HashMap多出了一个类Segment。 ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一个可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组。Segment的结构和HashMap类似,是一种数组和链表结构。一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一个HashEntry数组里的元素。当对HashEntry数组的数据进行修改时,必须首先获得与它对应的segment锁。 ConcurrentHashMap是使用了锁分段技术来保证线程安全的。 锁分段技术 :首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。 Hashtable容器在竞争激烈的并发环境下表现出效率低下的原因是因为所有访问Hashtable的线程都必须竞争同一把锁,假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术。首先将数据分成一段一段存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其它段的数据也能被其它线程访问。2023-07-16 15:46:241
hashmap和concurrenthashmap的区别是什么?
hashmap和concurrenthashmap的区别如下:HashMap不是线程安全的,而ConcurrentHashMap是线程安全的。ConcurrentHashMap采用锁分段技术,将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在。那么在插入元素的时候就需要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁。ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。HashMap:底层数组+链表实现,可以存储null键和null值,线程不安全。初始size为16,扩容:newsize = oldsize*2,size一定为2的n次幂。扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入。插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)。ConcurrentHashMap:底层采用分段的数组+链表实现,线程安全。通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。)。Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。2023-07-16 15:46:311
jdk8中的ConcurrentHashMap究竟为什么高效?
从源码来窥其一斑! 我们都知道hashMap不是线程安全的,因为在扩容方法中很容易出现死循环,hashTable使用锁的方式比较简单暴力,几乎在所有操作方法上都加了synchronized锁,导致总体性能很差,concurrentHashmap凭借线程安全且性能优异一直都是高并发中的首选key-value型数据结构; concurrentHashmap的高性能有以下原因: 一,分段锁:jdk8中对concurrentHashmap进行了改进,抛弃了jdk7中新建segment作为分段锁的过程,jdk8中虽沿用了这种分段锁的思想,却直接使用数组中的数据作为 分段锁保证concurrentHashmap在上锁的时候只针对数组下标下的数据进行上锁 (比如如果数组长度为256,那么每次put平均只有1/256的数据被锁),而大多数其他的数据还是能进行正常的增删改操作,无需阻塞等待,这无疑极大的 降低了锁的粒度,提升了性能。 二,红黑树 :jdk8中引入了红黑树结构,在单个数组下标内的数据达到8以后,会自动转换为红黑树进行存储, 使用大O表示法表示效率的话,红黑树的查找效率为O(log(n)),而链表的效率为O(n) ,当数据量越来越大的时候,红黑树的效率明显好于链表,所以concurrentHashmap性能得到很大提升; 现在我们主要从put方法中的主要方法来分析性能的提升: spread(key.hashCode());//作用是再次哈希,减少冲突 ,源码如下其中涉及到的位运算有 >>> 16:无符号右移16位,空位以0补齐 。 ^:异或运算符-->相同为0,不同为1; &:与运算符-->全1得1,否则0; (h ^ (h >>> 16)) & HASH_BITS; 所以这句代码的意思就是不仅消除高16位的影响,同时获得正整数的hash值 再来看后面的方法, 如上图: 1,就是判断当这个hash表还是空的时候,调用initTable进行初始化; 2,使用(n - 1) & hash)计算数组下标,如果数据指定下标处为null,则直接插入,注: cas是java8中的concurrentHashmap引入的线程安全判断,CAS算法做为乐观锁 ; 3,(fh = f.hash) == MOVED,走到此处说明下标内有node,且该node的值为-1(MODED=-1),搜索全类发现MODED是在调用有参构造器ForwardingNode中默认写入的,而这个调用处刚好在transfer方法中,所以我们推断,扩容的时候先将数组下标内的node.hash置为-1! 同时在3这一步中调用helpTransfer(tab, f)参与扩容,并把数据写入;4,走到这说明node不是空的,也没在扩容,那么锁住该下标下的node,并把新value插入链表中; 5,如果锁住的这个node能实例化为TreeBin,则代表已经转化为红黑树进行存储,将数据插入红黑树中; 6,判断在4,5中计算得到的数组下标内所有节点总数, 如果满足转化为红黑树的条件(节点数大于8),则自动转化为红黑树进行存储! 总的来说,concurrentHashmap之所以性能高就是因为使用了分段锁和红黑树! 至于conrrentHashmap其他的方法的源码分析,后期会补上的,更多的技术分享,敬请关注!2023-07-16 15:46:441
concurrent with是什么意思
同时 一致2023-07-16 15:47:102
ConcurrentHashMap常问问题
采用了分段锁的思想,将哈希桶数组分成一个个的Segment数组(继承ReentrantLock),每一个Segment里面又有多个HashEntry,也是被volatile修饰的,是为了保证在数组扩容时候的可见性,HashEntry中又有key,hash,value,next属性,而value,next又是被volatile修饰为了保证多线程环境下数据修改时的可见性,多线程环境下ConcurrentHashMap会对这些小的数组进行加锁,这样多线程操作Map就相当于是操作单线程环境下的HashMap,比如A线程对其中一个段进行写操作的时候线程B就不能对其进行写操作,但是线程B可以对其他的段进行写操作,从而实现并发修改和访问。 JDK1.8的ConcurrentHashMap摒弃了分段锁的思想,采用jdk1.8中HashMap的底层机构,Node数组+链表+红黑树。Node是继承了Entry的一个内部类,他的value和next都是被volatile修饰的原因也是为了保证多线程下修改数据的可见性。 采用CAS+synchronized实现更加细粒度的锁,将锁的级别控制在更细粒度的哈希桶数组元素的级别,只需要锁住链表头节点(红黑树的根节点)就不会影响到其他哈希桶数组元素的读写,大大的提高了并发度。 是不需要加锁的,因为Node节点使用了volatile修饰了value和next节点,而在jdk8中同样也是使用了volatile修饰了value和next节点,这样保证可见性了就不需要加锁了。 key不能为空,无法解释,没有什么可说的,可能就是作者的想法。 value不能为空是因为ConcurrentHashMap是工作在多线程环境下的,如果调用get方法,返回null,这个时候就存在二义性,因为ConcurrentHashMap不知道是没有这个key,还是这个key对应的值是不是null。所以干脆不支持value为null。 HashMap的迭代器是强一致性的,而ConcurrentHashMap的迭代器是弱一致性的,因为在多线程环境下,在创建迭代器的过程中,内部的元素会发生变化,如果是在已经遍历过去的数据中发生变化,迭代器是无法反映出来数据发生了改变,如果是发生在未迭代的数据时,这个时候就会反映出来,强一致性就是说只要迭代器创建出来之后数据就不会发生改变了。这样设计的好处就是迭代器线程可以使用原来的老数据进行遍历,写线程可以并发的完成改变,这样就保证了多个线程执行的时候的连续性和可拓展性,提升了并发性能。 JDK1.7中,并发度就是ConcurrentHashMap中的分段个数,即Segment[]数组的长度,默认是16,这个值可以在构造函数中设置。如果自己设置了并发度那么就会和HasHMap一样会去找到大于等于当前输入值的最小的2的幂指数作为实际并发度。如果过小就会产生锁竞争,如果过大,那么就会导致本来位于同一个Segment的的访问会扩散到不同的Segment中,导致性能下降。 JDK1.8中摈弃了Segment的概念,选择使用HashMap的结构,并发度依赖于数组的大小。 ConcurrentHashMap效率高,因为hashTable是给整个hash表加锁,而ConcurrentHashMap锁粒度要更低。 使用Collections.synchronizedMap(Map类型的对象)方法进行同步加锁,把对象转换为SynchronizedMap<K,V>类型。其实就是对HashMap做了一次封装,多个线程竞争一个mutex对象锁,在竞争激烈的情况下性能也非常差,不推荐使用。2023-07-16 15:47:171
concurrent.futures 模块怎么安装 或者concurrent 模块也可以
如果是python2.x,直接在命令提示符中用pip install futures语句安装,concurrent就可以用了。如果是python3,不用安装也可以用,自带了。参看:https://stackoverflow.com/questions/31086530/importerror-no-module-named-concurrent-futures-process2023-07-16 15:47:252
ConcurrentHashMap面试问题总结
Q:ConcurrentHashMap和HashMap的区别是什么? A: 1.ConcurrentHashMap是线程安全的,HashMap是线程不安全的 2.ConcurrentHashMap不允许Key为null的值插入。而HashMap是可以的 Q:JDK8的ConcurrentHashMap和JDK7的ConcurrentHashMap有什么区别? A: 1.JDK7的ConcurrentHashMap采用分段锁的策略,将整个数组分成多个segment,对这些segment进行分段加锁,使用的锁是ReentrantLock。而JDK8中的ConcurrentHashMap不采用分段锁的方式,直接使用Synchronized来进行。 2.JDK8中的ConcurrentHashMap新增了红黑树,并且插入用的是尾插法。 3.JDK7中的ConcurrentHashMap进行扩容时,是对当前的segment进行扩容,不会对其他segment有影响。而JDK8中就跟HashMap一样。整体扩容,但是保证线程安全 Q:JDK7中的ConcurrentHashMap是如何扩容的 A:JDK7中对每一段segment进行扩容,每一段segment的扩容跟HashMap保持一致 Q:JDK8中的ConcurrentHashMap是如何扩容的 A:在扩容时,首先会生成一个双倍大小的数组,生成完数组后,线程就会开始转移元素,在扩容的过程中,如果有其他线程在put,那么这个put线程会帮助去进行元素的转移,虽然叫转移,但是其实是基于原数组上的Node信息去生成一个新的Node的,也就是原数组上的Node不会消失,因为在扩容的过程中,如果有其他线程在get也是可以的。 Q:ConcurrentHashMap是如何保证线程安全的 A: 1.在JDK7的时候。ConcurrentHashMap是通过ReentrantLock+CAS+分段思想来保证的并发安全的,在JDK7的ConcurrentHashMap中,首先有一个Segment数组,存的是Segment对象,Segment相当于一个小HashMap,Segment内部有一个HashEntry的数组,也有扩容的阈值,同时Segment继承了ReentrantLock类,同时在Segment中还提供了put,get等方法,比如Segment的put方法在一开始就会去加锁,加到锁之后才会把key,value存到Segment中去,然后释放锁。同时在ConcurrentHashMap的put方法中,会通过CAS的方式把一个Segment对象存到Segment数组的某个位置中。同时因为一个Segment内部存在一个HashEntry数组,所以和HashMap对比来看,相当于分段了,每段里面是一个小的HashMap,每段公用一把锁,同时在ConcurrentHashMap的构造方法中是可以设置分段的数量的,叫做并发级别concurrencyLevel. 2.在JDK8的时候,ConcurrentHashMap是通过synchronized+cas来实现了。在JDK8中只有一个数组,就是Node数组,Node就是key,value,hashcode封装出来的对象,和HashMap中的Entry一样,在JDK8中通过对Node数组的某个index位置的元素进行同步,达到该index位置的并发安全。同时内部也利用了CAS对数组的某个位置进行并发安全的赋值。2023-07-16 15:47:321
同时地英语怎么说
问题一:在同时的英语表达 同时 的 六种表达法: at the same time meanwhile in the meantime simultaneously moreover besides 问题二:在 ....的同时 英语怎么说 While During 问题三:同时的英语短语怎么讲 一边忙于毕业论文一边找工作 I"m busy with my paper as well as finding a job 问题四:“与此同时”的英文怎么说 “与此同时”在英文里有多种表达方式,根据句式而有所不同,如下将分别举例说明: Meanwhile是副词,一般用于句首; at the same time作状语,一般放在句末; 除此以外,还可以用修饰动词的副词concurrently,表达“同时(做)...”的意思。例句:Furthermore, all these dharmas are to be understood as concurrently present in the dharmadhatu. From 问题五:“一起”的英语怎么说 不同的语境用法不同: 单纯的一起就是together, 一对恋人在一起(我想和你一起I wanna be with you) 一起走(I want you to e with me 我想让你和我一起走)量词,比如“一起事件 an incidence 问题六:同时发生的的英文,同时发生的的翻译,怎么用英语翻译 同时发生的 simultaneous;concurrent;instantaneous;coinstantaneous更多释义>> [网络短语] 同时发生的 simultaneous;concurrent;coinstantaneous 同时发生的事件 concurrent 同时发生的概率 PF,E 问题七:”在提高性能的同时“英语怎么说 While improving performance,... 问题八:问题与解决问题的方法总是同时存在。 用英语怎么说,不要百度翻译的。 Solutions always e with questions. 问题九:和......在一起用英语怎么说 be with *** 和谁在一起 例如 I want to be with you。 我想和你在一起 do sth with *** 和某人一起做某事 例如 I do homework with you 我和你一起做功课 do sth with sth 用某事来做某事 例如 I wash the clothes with water 我用水洗衣服 希望可以帮到你2023-07-16 15:47:391
如何在java中使用ConcurrentHashMap
参考如下内容:ConcurrentHashMap锁的方式是稍微细粒度的。 ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。试想,原来 只能一个线程进入,现在却能同时16个写线程进入(写线程才需要锁定,而读线程几乎不受限制,之后会提到),并发性的提升是显而易见的。更令人惊讶的是ConcurrentHashMap的读取并发,因为在读取的大多数时候都没有用到锁定,所以读取操作几乎是完全的并发操作,而写操作锁定的粒度又非常细,比起之前又更加快速(这一点在桶更多时表现得更明显些)。只有在求size等操作时才需要锁定整个表。而在迭代时,ConcurrentHashMap使用了不同于传统集合的快速失败迭代器的另一种迭代方式,我们称为弱一致迭代器。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出 ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数 据,iterator完成后再将头指针替换为新的数据,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变,更重要的,这保证了多个线程并发执行的连续性和扩展性,是性能提升的关键。下面分析ConcurrentHashMap的源码。主要是分析其中的Segment。因为操作基本上都是在Segment上的。先看Segment内部数据的定义。2023-07-16 15:47:461
如何正确使用QtConcurrent运行类成员函数
使用QtConcurrent的代码如下:void MainDialog::on_pushButton_toGrayImage_QConcurrent_clicked(){ QFuture<QImage*> future = QtConcurrent::run(this,&MainDialog::processImageByQtConcurrent); //imageAfterProceess 这个指针变量之前被无视,现在终于找到存在感了 this->imageAfterProceess = future.result(); //接收处理结果 this->showImageInNewWindow(this->imageAfterProceess);//新窗口显示处理后的图像}2023-07-16 15:48:072
java concurrenthashmap和hashmap的区别
即使是线程安全的集合,使用iterator()进行迭代都是不安全的,必须手动地进行同步,下面是JavaDoc的说明:Itisimperativethattheusermanuallysynchronizeonthereturnedmapwheniteratingoveranyofitscollectionviews:Mapm=Collections.synchronizedMap(newHashMap());Sets=m.keySet();//Needn"tbeinsynchronizedblocksynchronized(m){//Synchronizingonm,nots!Iteratori=s.iterator();//Mustbeinsynchronizedblockwhile(i.hasNext())foo(i.next());}如果不使用同步块进行迭代,当在迭代时,如果存在另外一个线程对集合进行删除或者添加元素,则会报ConcurrentModificationException2023-07-16 15:48:183
如何正确使用QtConcurrent运行类成员函数
使用QtConcurrent的代码如下:void MainDialog::on_pushButton_toGrayImage_QConcurrent_clicked(){ QFuture<QImage*> future = QtConcurrent::run(this,&MainDialog::processImageByQtConcurrent); //imageAfterProceess 这个指针变量之前被无视,现在终于找到存在感了 this->imageAfterProceess = future.result(); //接收处理结果 this->showImageInNewWindow(this->imageAfterProceess);//新窗口显示处理后的图像}2023-07-16 15:48:381
java.util.concurrent.cancellationexception怎么解决
uservo user=(uservo)voinfo;String username=user.getUsername();String password=user.getPassword();System.out.println("your username is "+username);System.out.println("your password is "+password);List list = new ArrayList();2023-07-16 15:48:471
Concurrent包中线程池问题:java中主函数执行完了为什么主线程还没有退出?是因为啥?都已经输出了横杠了.
那是因为你线程池没有关闭,所以主线程就不会退出,需要主线程退出只需要调用线程池的shutdown()方法,你的代码可以在main方法的最后一行加上 thr.shutdown(); 就可以了。2023-07-16 15:48:551
为什么CMS GC时出现Concurrent Mode Failure
并发收集器(concurrentcollector)指的是回收年老代和持久代时,采用多个线程和应用线程并发执行,减少应用停顿时间,但如果参数设置不当,容易出现Concurrent ModeFailure现象,此时JVM将采用停顿的方式进行full gc,整个gc时间相当可观,完全违背了采用CMS GC的初衷。 出现此现象的原因主要有两个:一个是在年老代被用完之前不能完成对无引用对象的回收;一个是当新空间分配请求在年老代的剩余空间中得到满足。原文如(if theconcurrent collector is unable to finish reclaiming the unreachable objectsbefore the tenured generation fills up, or if an allocation cannot be satisfiedwith the available free space blocks in the tenured generation, then theapplication is paused and the collection is completed with all the applicationthreads stopped)。出现此现象的具体gc日志如下:90003.167: [GC 90003.167: [ParNew: 261760K->0K(261952K), 0.0204310secs] 778897K->520196K(1310528K), 0.0207190 secs]90006.049: [GC 90006.050: [ParNew: 261760K->0K(261952K), 0.0136380 secs]781956K->521446K(1310528K), 0.0138720 secs]90010.628: [GC 90010.628: [ParNew: 261760K->261760K(261952K), 0.0000350secs]90010.628: [CMS (concurrent mode failure)[Unloadingclass sun.reflect.GeneratedSerializationConstructorAccessor1818][Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1816][Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1819][Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1821][Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1817][Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1822][Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1820]: 521446K->415777K(1048576K), 2.2550270 secs] 783206K->415777K(1310528K),2.2553820 secs]90015.099: [GC 90015.099: [ParNew: 261760K->0K(261952K), 0.0198180 secs]677537K->418003K(1310528K), 0.0200650 secs]90018.670: [GC 90018.670: [ParNew: 261760K->0K(261952K), 0.0131610 secs]679763K->419115K(1310528K), 0.0133750 secs]90022.254: [GC 90022.254: [ParNew: 261760K->0K(261952K), 0.0151240 secs]680875K->420505K(1310528K), 0.0154180 secs]当时的JVM参数如下:-server -Xms1280m -Xmx1280m -Xmn256m -Xss256k -XX:PermSize=128m-XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC-XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled-XX:+DisableExplicitGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps因为配置了+CMSClassUnloadingEnabled参数,所以出现Unloading classsun.reflect.GeneratedSerializationConstructorAccessor的日志,这是个好习惯,如果空间不够时可以卸载类来释放空间,以进行FULL GC,相反,如果gc日志中出现了此日志,应该检查各代的大小设置是否合理。这里应用从启动到上述现象出现时还没有进行过CMS GC,出现concurrent modefailure现象的原因是年轻代GC(ParNew),年老代所剩下的空间不足以满足年轻代,也就是开头提到的原因二。要避免此现象,方法一是降低触发CMS的阀值,即参数-XX:CMSInitiatingOccupancyFraction的值,默认值是68,所以这里调低到50,让CMS GC尽早执行,以保证有足够的空间,如下:-server -Xms1280m -Xmx1280m -Xmn256m -Xss256k -XX:PermSize=128m-XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC-XX:CMSFullGCsBeforeCompaction=1 -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=50-XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -verbose:gc-XX:+PrintGCDetails -XX:+PrintGCTimeStamps调完之后发现还是一样的现象(这里有点不是很明白,年老代空间为1024m(1280m-256m),50%时触发CMS GC,也就是在年老代512m的时候,剩下的堆空间有512m,就算年轻代全部装进去应该也是够的),所以怀疑是年轻代太大,有大的对象,在年老代有碎片的情况下将很难分配,所以有了第二个解决办法,即减少年轻代大小,避免放入年老代时需要分配大的空间,同时调整full gc时压缩碎片的频次,减少持久代大小,以及将触发CMS GC的阀值适当增大(因为年轻代小了,这个调大点没关系,后面可以再调试这个参数),参数如下:-server -Xms1280m -Xmx1280m -Xmn128m -Xss256k -XX:PermSize=96m -XX:MaxPermSize=96m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSFullGCsBeforeCompaction=1 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps调整完后没有那个现象了,这里主要起作用的就是调小年轻代大小。在年老代到达826m(触发CMS阀值(1280-128)*0.7=806m)时出现了CMS GC,用时27ms,日志如下:705.444: [GC 705.445: [ParNew: 130944K->0K(131008K), 0.0197680 secs]954628K->826284K(1310656K), 0.0199720 secs]705.467:[GC [1 CMS-initial-mark: 826284K(1179648K)] 826744K(1310656K), 0.0271540 secs]705.494:[CMS-concurrent-mark-start]706.717:[CMS-concurrent-mark: 1.223/1.223 secs]706.717:[CMS-concurrent-preclean-start]706.717:[CMS-concurrent-preclean: 0.000/0.000 secs]706.742:[CMS-concurrent-abortable-preclean-start]706.742:[CMS-concurrent-abortable-preclean: 0.000/0.000 secs]707.067: [GC 707.067: [ParNew: 130944K->0K(131008K), 0.0160200 secs]957228K->827348K(1310656K), 0.0162110 secs]707.796: [GC[YG occupancy: 66671 K (131008 K)]707.796: [Rescan (parallel) ,0.0278280 secs]707.824: [weak refs processing, 0.0420770 secs] [1 CMS-remark:827348K(1179648K)] 894019K(1310656K), 0.0711970 secs]707.877: [CMS-concurrent-sweep-start]708.453: [GC 708.454: [ParNew: 130944K->0K(131008K), 0.0203760 secs]848439K->718796K(1310656K), 0.0205780 secs]709.833: [GC 709.833: [ParNew: 130944K->0K(131008K), 0.0160170 secs]430484K->301411K(1310656K), 0.0161840 secs]709.916: [CMS-concurrent-sweep: 1.974/2.040 secs]709.916: [CMS-concurrent-reset-start]709.951: [CMS-concurrent-reset: 0.034/0.034 secs]711.187: [GC 711.187: [ParNew: 130944K->0K(131008K), 0.0130890 secs]413136K->283326K(1310656K), 0.0132600 secs]观察一段时间的gc情况,gc效率也很高,单次YGCT<20ms,FGCT <40ms:$ jstat -gcutil 31935 1000 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 0.00 64.29 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.33 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.41 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.45 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.49 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.58 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.63 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.69 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.72 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.75 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.79 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.84 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.90 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.95 36.47 73.15 1293 19.514 6 0.211 19.725 0.00 0.00 64.99 36.47 73.15 1293 19.514 6 0.211 19.725这时,想再测试下-XX:CMSInitiatingOccupancyFraction的值,调到80时又出现了上述现象Concurrent ModeFailure,启动后还没进行过CMS GC,在年老代914m时就出现了:759.994: [GC 759.994: [ParNew: 130944K->0K(131008K), 0.0172910 secs]1040896K->911480K(1310656K), 0.0174730 secs]760.879: [GC 760.879: [ParNew: 130944K->0K(131008K), 0.0300920 secs]1042424K->914190K(1310656K), 0.0302950 secs]761.768: [GC 761.769: [ParNew: 130944K->130944K(131008K), 0.0000340secs]761.769: [CMS (concurrent mode failure)[Unloading classsun.reflect.GeneratedMethodAccessor342]edMethodAccessor348][Unloading class sun.reflect.GeneratedMethodAccessor411][Unloading class sun.reflect.GeneratedMethodAccessor407][Unloading class sun.reflect.GeneratedMethodAccessor541]最后总结下,出现Concurrent ModeFailure现象时,解决办法就是要让年老代留有足够的空间,以保证新对象空间的分配。另外在JVM BUG中有提到,JDK1.5_09版本之前,JVM参数-XX:CMSInitiatingOccupancyFraction是无效的,我这里应用环境的版本是JDK1.5_08,从gc日志来看是可以生效的。GC时还有一个常见的错误PromotionFailed,解决办法类似,也是调整年轻代和年老代的比例,还有CMSGC的时机。2023-07-16 15:49:021
为什么java.util.concurrent 包里没有并发的ArrayList实现
你包引错了吧,让他自动引,如果还没有就是版本低了,要1.5还是1.6后面才有这个2023-07-16 15:49:112
java.util.concurrent.atomic的可变规则
原子访问和更新的内存效果一般遵循以下可变规则:get 具有读取 volatile 变量的内存效果。set 具有写入(分配) volatile 变量的内存效果。weakCompareAndSet 以原子方式读取和有条件地写入变量,并对于该变量上的其他内存操作进行排序,否则将充当普通的非可变内存操作。compareAndSet 和所有其他的读取和更新操作(如 getAndIncrement)都有读取和写入 volatile 变量的内存效果。除了包含表示单个值的类之外,此包还包含 Updater 类,该类可用于获取任意选定类的任意选定 volatile 字段上的 compareAndSet 操作。AtomicReferenceFieldUpdater、AtomicIntegerFieldUpdater 和 AtomicLongFieldUpdater 是基于反射的实用工具,可以提供对关联字段类型的访问。它们主要用于原子数据结构中,该结构中同一节点(例如,树节点的链接)的几个 volatile 字段都独立受原子更新控制。这些类在如何以及何时使用原子更新方面具有更大的灵活性,但相应的弊端是基于映射的设置较为拙笨、使用不太方便,而且在保证方面也较差。AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray 类进一步扩展了原子操作,对这些类型的数组提供了支持。这些类在为其数组元素提供 volatile 访问语义方面也引人注目,这对于普通数组来说是不受支持的。AtomicMarkableReference 类将单个布尔值与引用关联起来。例如,可以在数据结构内部使用此位,这意味着引用的对象在逻辑上已被删除。AtomicStampedReference 类将整数值与引用关联起来。例如,这可用于表示与更新系列对应的版本号。2023-07-16 15:49:181
concurrenthashmap是线程安全的吗
这样使用是有问题的。ConcurrentMap能够保证每一次调用(例如一次putIfAbsent)都是原子操作,不受多线程影响,但并不保证多次调用之间也是原子操作。以上实现的GetKeyBM方法中,ConcurrentMap的方法被调用了许多次,不同线程之间必然存在着竞争关系,导致最终结果不正确。现在的目标是,将下面描述的这一系列操作作为原子操作:“对每个分出来的词通过调用GetKeyBM方法,如果存在,则取出对应的编码,如果不存在,则加入KeyTotal中,并且给予一个编码,就是KeyTotal中的变量数加一”最直观的方法就是整块同步:synchronized (KeyTotal) {Integer value = KeyTotal.get(word);if (value == null) {value = KeyTotal.size() + 1;KeyTotal.put(word, value);}}这样,使用普通的map就可以了。如果你使用的是Java 8的话,ConcurrentMap有一个类似的方法 computeIfAbsent 可以使用:KeyTotal.computeIfAbsent(word, k -> KeyTotal.size() + 1);这样才能确保一次原子操作。computeIfAbsent方法的作用是,如果word键值不存在,则使用第二个参数来生成一个值放入map中,等价于以下代码,并且是原子操作:V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction):if (map.get(key) == null) {V newValue = mappingFunction.apply(key);if (newValue != null)return map.putIfAbsent(key, newValue);}正好与你的目标是一致的。2023-07-16 15:49:321
ConCurrentHashMap 1.7 和 1.8 的区别
ConCurrentHashMap 1.8 相比 1.7的话,主要改变为: 下面简单介绍下主要的几个方法的一些区别: JDK1.7中的实现: ConCurrentHashMap 和 HashMap 的put()方法实现基本类似,所以主要讲一下为了实现并发性,ConCurrentHashMap 1.7 有了什么改变 JDK1.8中的实现: JDK1.7中的实现: JDK1.8中的实现: JDK1.7中的实现: JDK1.8中的实现: JDK1.7中的实现: JDK1.8中的实现: 由于没有segment的概念,所以只需要用一个 baseCount 变量来记录ConcurrentHashMap 当前 节点的个数 。2023-07-16 15:49:391
HashMap HashTable和ConcurrentHashMap的区别
最大的区别就是ConcurrentHashMap是线程安全的,hashMap不是线程安全的。为什么线程安全呢:ConcurrentHashMap代码中可以看出,它引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中:2023-07-16 15:49:482
为什么CMS GC时出现Concurrent Mode Failure
出现Concurrent ModeFailure现象时,解决办法就是要让年老代留有足够的空间,以保证新对象空间的分配。另外在JVM BUG中有提到,JDK1.5_09版本之前,JVM参数-XX:CMSInitiatingOccupancyFraction是无效的,我这里应用环境的版本是JDK1.5_08,从gc日志来看是可以生效的。GC时还有一个常见的错误PromotionFailed,解决办法类似,也是调整年轻代和年老代的比例,还有CMSGC的时机。2023-07-16 15:50:221
为什么java.concurrent.automic 里面没有string
因为String不是基础类型,而是对象,且是个Value Object(值对象)。你无法改变一个String对象的内容,你只能用另一个String的对象来替换原有的引用。例如:int i = 0;i++;//改变了原来的值String s = "xxx";//你无法改变原来的值s = "abc";//只能使用另外一个对象来替换因此atomic封装的String没有任何用处。atomic包是工具包,只是提供一个方便处理并发计数、改变标志的工具类,不能替代原来的基础类型和对象使用。2023-07-16 15:50:291
hashmap和concurrenthashmap哪个是线程安全的,为什么线程安全
ConcurrentHashMap是线程安全的,而HashMap不是线程安全的。在多线程环境下,如果多个线程同时读写同一个HashMap对象,可能会导致数据不一致的问题,例如两个线程同时往HashMap中添加数据,可能会导致数据丢失或覆盖。这是因为HashMap的实现不是线程安全的,它的内部结构是由数组和链表组成的,多个线程同时对它进行操作,会导致链表形成环形或链表断裂,导致数据读取或修改错误。ConcurrentHashMap是线程安全的原因是它采用了分段锁的机制,将HashMap分成若干个段(Segment),每个Segment独立地加锁,不同的线程可以同时访问不同的Segment,从而避免了多个线程同时访问同一个Segment的情况。这种机制可以提高并发访问效率,保证了线程安全性。2023-07-16 15:50:361
concurrenthashmap的读是否要加锁,为什么
。有并发访问的时候用ConcurrentHashMap,效率比用锁的HashMap好功能上可以,但是毕竟ConcurrentHashMap这种数据结构要复杂些,如果能保证只在单一线程下读写,不会发生并发的读写,那么就可以试用HashMap。ConcurrentHashMap读不加锁,写只加部分锁。在多线程下得高性能读写用比较好。但是这也是要用空间换时间来的。如果我的回答没能帮助您,请继续追问。2023-07-16 15:50:441
A child container failed during start。 tomcat启动报错
遇到这个问题的小伙伴,看看是不是和我遇到的问题一样。(问题已解决)我本地环境项目好的,但是我同事的却报:A child container failed during start最后我将我本地打成的war包和他打成的war包内的jar包对比,发现bcprov-jdk16这个包不一样。使用bcprov-jdk16包 需要在本地运行的时候 如果出现找不到某某类的时候 需要将这个jar包加入jre环境下,将bcprov-jdk16-146.jar 放入 本机 jre/lib/ext 下 即可。(本句来自:网页链接)然后就正常了。2023-07-16 15:50:523
concurrenthashmap支持高并发的原理,段锁为什么要采用重入锁而不是synchronized
ConcurrentHashMap只是保证本身map的线程安全,不保证你自己写的程序的同步.你可以采用客户端加锁实现同步synchronized(test.chm)2023-07-16 15:51:161
concurrent.jar 包是做什么用的
jar包就是别人已经写好的一些类,然后将这些类进行打包,你可以将这些jar包引入你的项目中,然后就可以直接使用这些jar包中的类和属性了,这些jar包一般都会放在lib目录下的...呵呵2023-07-16 15:51:231
java8 中concurrenthashmap数据结构和HashMap一样,且线程安全 为什么还要HashMap
java是编程语言里比较难学的一门,如果有心从事编程方向的工作,最好到专业机构学习并有更多的项目实践,更贴近市场,这样更有利于将来的发展。2023-07-16 15:51:345
为什么java.util.concurrent包没有concurrentList
有个CopyOnWriteArrayList2023-07-16 15:52:022
ConcurrentHashMap内部排序的使用
业务中,我们经常会有队map进行排序的要求,如下将会详细讲解如何利用java8的lambda表达式实现map的内部排序。 首先,我们先构造一个person类: public class Person { private String addr; private String age; } 测试,对map进行排序处理。 import com.ky.common.Person; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Map.Entry.comparingByValue; import static java.util.stream.Collectors.toMap; public class Test { stream.sorted(Comparator.comparingInt(Map.Entry::getValue)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2)->e2, ConcurrentHashMap::new)); map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(System.out::println); }2023-07-16 15:52:091
如何正确使用QtConcurrent运行类成员函数
使用QtConcurrent的代码如下:void MainDialog::on_pushButton_toGrayImage_QConcurrent_clicked(){QFuture<QImage*> future = QtConcurrent::run(this,&MainDialog::processImageByQtConcurrent);//imageAfterProceess 这个指针变量之前被无视,现在终于找到存在感了this->imageAfterProceess = future.result(); //接收处理结果this->showImageInNewWindow(this->imageAfterProceess);//新窗口显示处理后的图像}2023-07-16 15:52:441
java.util.concurrent.Future.isDone是否有必要
有必要,因为get方法会一直等待资源返回,可以用isDone判断Future.get()方法会一直阻塞,直到有数据返回,这时候isDone()是true.那么在get()之前判断isDone()是否有必要?如下:if (!future.isCancelled()){ HotelSearchResponse response = null; if (future.isDone()) //这里有没有必要判断 { if (future.get() != null) { response = future.get(); } else { while (!future.isDone())//这个while有没有必要 { if (future.get() != null) { response = future.get(); } } }}2023-07-16 15:52:531
collections.synchronizedmap和concurrenthashmap的区别
最大的区别就是ConcurrentHashMap是线程安全的,hashMap不是线程安全的。为什么线程安全呢:ConcurrentHashMap代码中可以看出,它引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中:2023-07-16 15:53:081
backport-util-concurrent是什么
backport-util-concurrent.jar并发访问处理端口的工具包。是LCDS的一部分2023-07-16 15:53:161
java.util.concurrent.Future.isDone是否有必要
有必要,因为get方法会一直等待资源返回,可以用isDone判断 Future.get()方法会一直阻塞,直到有数据返回,这时候isDone()是true.那么在get()之前判断isDone()是否有必要?如下: if (!future.isCancelled()) { HotelSearchResponse response = ...2023-07-16 15:53:331
concurrent session是什么意思
并行会议2023-07-16 15:53:524
aix 如何判断vg是concurrent
比较vg的pvid,如果一样,说明这个vg是shared,算是concurrent2023-07-16 15:54:001
java开发 怎么控制 每秒并发数?
java.util.concurrent.Executors里有很多方法创建固定个数的线程池使用线程池应该可以吧2023-07-16 15:54:082
newfixedthreadpool 怎么控制超时的线程
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。看代码:Java代码 收藏代码<span style="font-size: small;">package test;import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;public class ExecutorTest {public static void main(String args[]) {Random random = new Random();//产生一个 ExecutorService 对象,这个对象带有一个大小为 poolSize 的线程池,若任务数量大于 poolSize ,任务会被放在一个 queue 里顺序执行。ExecutorService executor = Executors.newFixedThreadPool(3);// 判断可是线程池可以结束int waitTime = 500;for (int i = 0; i < 10; i++) {String name = "线程 " + i;int time = random.nextInt(1000);waitTime += time;Runnable runner = new ExecutorThread(name, time);System.out.println("增加: " + name + " / " + time);executor.execute(runner);}try {Thread.sleep(waitTime);executor.shutdown();executor.awaitTermination(waitTime, TimeUnit.MILLISECONDS);} catch (InterruptedException ignored) {}} }2023-07-16 15:54:161
verilog 编译错误:Concurrent assignment to a non-net registerr is not permitted
调用子模块时 输出端口只能用wire类型变量进行映射 这是verilog语法规定的不知道你说的“无法实现想要的功能”是指什么 但是如果你需要输出信号是reg类型可以增加一个wire类型中间变量 再把这个中间变量赋值给一个reg类型变量wire a;testmodule tss(dataa,a,clockk);reg registerr;always @ * registerr <= a;2023-07-16 15:54:242
ConcurrentHashMap 中putIfAbsent 和put的区别
Java中ConcurrentHashMap putifAbsent方法的例子很多时候我们希望在元素不存在时插入元素,我们一般会像下面那样写代码synchronized(map){if (map.get(key) == null){return map.put(key, value);} else{return map.get(key);}}上面这段代码在HashMap和HashTable中是好用的,但在CHM中是有出错的风险的。这是因为CHM在put操作时并没有对整个Map加锁,所以一个线程正在put(k,v)的时候,另一个线程调用get(k)会得到null,这就会造成一个线程put的值会被另一个线程put的值所覆盖。当然,你可以将代码封装到synchronized代码块中,这样虽然线程安全了,但会使你的代码变成了单线程。CHM提供的putIfAbsent(key,value)方法原子性的实现了同样的功能,同时避免了上面的线程竞争的风险。2023-07-16 15:55:071
为什么java.util.concurrent 包里没有并发的ArrayList实现
ArrayList 是非线程安全的,这点已经在文档中指出来了。如果你想要一个线程安全的就用 CopyOnWriteArrayList。它在修改时把数据复制一份再来修改,因此后续修改不影响正在跑迭代的其它线程。如果你需要一个同步的就可以直接 List synchronizedList = Collections.synchronizedList(new ArrayList());每种实现类都有它的优势和缺点,按我们的需要选择一个合适的就可以了。2023-07-16 15:55:181
named user 和 concurrent user的区别
从概念上说 前者(web_concurrent_start)是语句的并发 后者(lr_rendezvous)是user的并发 这是两件完全完全不同的事情 没有什么可以比较的 仅仅只是都有“同时执行”的意思而已 详细来说2023-07-16 15:55:251
请问“并发选收”/“并发优收”/“双发选收”用英文怎么说? 谢谢!
concurrent xuanshouconcurrent optimal chargedouble xuanshou网上找的 你的名词太难了 没办法2023-07-16 15:55:332
java定时任务怎么实现
/*** 普通thread* 这是最常见的,创建一个thread,然后让它在while循环里一直运行着,* 通过sleep方法来达到定时任务的效果。这样可以快速简单的实现,代码如下:* @author GT**/public class Task1 {public static void main(String[] args) {// run in a secondfinal long timeInterval = 1000;Runnable runnable = new Runnable() {public void run() {while (true) {// ------- code for task to runSystem.out.println("Hello !!");// ------- ends heretry {Thread.sleep(timeInterval);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread thread = new Thread(runnable);thread.start();}} [java] view plain copyimport java.util.Timer;import java.util.TimerTask;/**** 于第一种方式相比,优势 1>当启动和去取消任务时可以控制 2>第一次执行任务时可以指定你想要的delay时间** 在实现时,Timer类可以调度任务,TimerTask则是通过在run()方法里实现具体任务。 Timer实例可以调度多任务,它是线程安全的。* 当Timer的构造器被调用时,它创建了一个线程,这个线程可以用来调度任务。 下面是代码:** @author GT**/public class Task2 {public static void main(String[] args) {TimerTask task = new TimerTask() {@Overridepublic void run() {// task to run goes hereSystem.out.println("Hello !!!");}};Timer timer = new Timer();long delay = 0;long intevalPeriod = 1 * 1000;// schedules the task to be run in an intervaltimer.scheduleAtFixedRate(task, delay, intevalPeriod);} // end of main} [java] view plain copyimport java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/***** ScheduledExecutorService是从Java SE5的java.util.concurrent里,做为并发工具类被引进的,这是最理想的定时任务实现方式。* 相比于上两个方法,它有以下好处:* 1>相比于Timer的单线程,它是通过线程池的方式来执行任务的* 2>可以很灵活的去设定第一次执行任务delay时间* 3>提供了良好的约定,以便设定执行的时间间隔** 下面是实现代码,我们通过ScheduledExecutorService#scheduleAtFixedRate展示这个例子,通过代码里参数的控制,首次执行加了delay时间。*** @author GT**/public class Task3 {public static void main(String[] args) {Runnable runnable = new Runnable() {public void run() {// task to run goes hereSystem.out.println("Hello !!");}};ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);}}2023-07-16 15:55:511