

您好,欢迎访问上海贝乐莉网络科技有限公司!
ArrayList是线程担心齐的,那面千真万确。由于ArrayList的全部办法既不添锁,也不停止特地的线程平安处置。
而Vector动作线程平安版的ArrayList,永存感老是较为矮。由于不管是add、remove仍是get办法皆加入了synchronized锁,因而服从卑下。
偶然中瞧到挖金中有人写了如许1遍作品(尔花了二地利间出处理的题目,chatgpt用了5秒弄定)
瞧到末了,毕竟来讲是1个多线程停的并提问题,有些人大概以为那个题目很强,然则咋道呢,尔也逢上了。
由于尔按寻常逻辑写了1段代码,须要从数据库查问7次数据,之后出现屡屡盘查的快度出格缓,因为交易缘故SQL久时没法劣化。
此时料到1个处理规划,便是多条退步行,以停代码模仿了基础淌程
packagecom.example.springboot;importcn.hutool.core.date.DateUtil;importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.Executors;importjava.util.concurrent.ThreadPoolExecutor;publicclassIpTest{publicstaticvoidmain(String[]args){List<String>reList=newArrayList<>();ThreadPoolExecutorpool=(ThreadPoolExecutor)Executors.newFixedThreadPool(7);CountDownLatchcountDownLatch=newCountDownLatch(7);//1周for(inti=0;i<7;i++){CompletableFuture.supplyAsync(()->{try{reList.add(DateUtil.now());}catch(Exceptione){e.printStackTrace();}finally{countDownLatch.countDown();//同步施行停止}returnnull;},pool);}//共步等候查问了局try{countDownLatch.await(30,TimeUnit.SECONDS);}catch(InterruptedExceptione){}reList.stream().forEach(s->System.out.println(s));pool.shutdown();}}CountDownLatch用于干线程断绝期待子使命施行完成,参照(Future体制本质运用)
CompletableFuture用于同步施行职责,注重必须正在finally中开释countDownLatch,不然干线程会平昔停顿30秒。
屡次运转那个法式,您会觉察1个题目,偶尔会挨印出去空
2023-06-2909:45:42null2023-06-2909:45:422023-06-2909:45:422023-06-2909:45:422023-06-2909:45:42缘故便是由于ArrayList没有是线程平安。
处理规划有二种
(1)应用synchronized关头字
CompletableFuture.supplyAsync(()->{try{synchronized(reList){reList.add(DateUtil.now());}}catch(Exceptione){e.printStackTrace();}finally{countDownLatch.countDown();//同步施行停止}returnnull;},pool);(2)应用CopyOnWriteArrayList取代
List<String>reList=newCopyOnWriteArrayList<>();对于CopyOnWriteArrayList的诠释,网上1年夜堆,那里面到为行。
那里复杂道停,CopyOnWriteArrayList没有管是add也罢,仍然remove也罢。皆是经由过程ReentrantLock + volatile + 数组拷贝去完成线程平安的。
并且屡屡add/remove掌握城市启示新数组,会占用体系内乱存。
然则生活必定也是有利益的,便是get(int index)没有须要添锁,原因CopyOnWriteArrayList正在add/remove操纵时,没有会修正本数组,因此读操纵没有会生活线程平安题目。那本来便是读写别离的想法,惟有写进的时分才添锁,复造正本去停止修正。CopyOnWriteArrayList也啼写时复造容器。
并且正在迭代进程中,便使数组的构造被转变也没有会扔出ConcurrentModificationException同常。由于迭代的一直是本数组,而全部的转变皆爆发正在本数组的正本上。因此对迭代器来讲,迭代的聚合构造没有会产生转变。
归纳:CopyOnWriteArrayList的长处重要有二个:
线程平安
年夜年夜的抬高了“读”操纵的并收度(比拟于Vector)
坏处也很鲜明:
屡屡“写”操纵城市启示新的数组,虚耗空间
没法保护及时性,由于“读”战“写”没有正在统一个数组,且“读”操纵不添互斥锁,因此没有能包管强分歧性,只可担保终究分歧性
add/remove操纵服从矮,既要添锁,借要拷贝数组
因而CopyOnWriteArrayList较为相宜读多写少的场景。
推举您浏览更多相关于“ list多线程线程平安CopyOnWriteArrayList ”的作品