Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand Java concurrent Container J.U.C

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/01 Report--

This article shows you how to understand the Java concurrent container J.U.C, the content is concise and easy to understand, can definitely brighten your eyes, through the detailed introduction of this article, I hope you can get something.

> J.U.C is short for java.util.concurrent and provides many thread-safe collections.

CopyOnWriteArrayList introduction

> CopyOnWriteArrayList is thread-safe compared to ArrayList, which literally means copying during write operations. CopyOnWriteArrayList uses the write-time replication technique to copy a copy from the original array when a new element needs to be added. Then add a lock to the new array, and after adding, point the reference to the original array to the new array.

Public boolean add (E e) {final ReentrantLock lock = this.lock; lock.lock (); / / locked try {Object [] elements = getArray (); int len = elements.length; Object [] newElements = Arrays.copyOf (elements, len + 1); newElements [len] = e; / / reference points to change setArray (newElements) Return true;} finally {lock.unlock (); / / release lock}}

> the add operation of CopyOnWriteArrayList obtained from the above source code is completed under the protection of locking. The purpose of locking is to make multiple copies and mess up the data when multithreading CopyOnWriteArrayList concurrently add.

Public E get (int index) {return get (getArray (), index);}

> the above code shows that get is unlocked

> if concurrent get occurs, there will be the following three situations.

If the write operation is not completed, read the data from the original array directly

If the write operation is complete, but the reference does not point to the new array, then the original array data is also read

If the write operation is complete and the reference already points to the new array, read the data directly from the new array.

CopyOnWriteArrayList multithreaded code demonstration. Package com.rumenz.task;import java.util.List;import java.util.concurrent.*;// thread safety public class CopyOnWrireArrayListExample {public static Integer clientTotal=5000; public static Integer threadTotal=200; private static List list=new CopyOnWriteArrayList (); public static void main (String [] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool (); final Semaphore semaphore=new Semaphore (threadTotal); final CountDownLatch countDownLatch=new CountDownLatch (clientTotal); for (int I = 0; I

< clientTotal; i++) { final Integer j=i; executorService.execute(()->

{try {semaphore.acquire (); update (j); semaphore.release ();} catch (Exception e) {e.printStackTrace ();} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); System.out.println ("size:" + list.size ());} private static void update (Integer j) {list.add (j);}} / / size:5000CopyOnWriteArrayList usage scenarios

Due to the need to copy the original array when add, if the original array content is relatively large, it may result in young gc and full gc.

For scenarios that cannot be used for real-time reading, such as copying arrays, it takes time to add new elements, so it is possible to get old data after calling get operation. Although CopyOnWriteArrayList can achieve final consistency, there is no way to meet the real-time requirements.

CopyOnWriteArrayList is suitable for scenarios with more reading and less writing, such as whitelist, blacklist and so on.

CopyOnWriteArrayList is not suitable for high-performance Internet applications because it needs to copy arrays when add.

CopyOnWriteArraySet introduces public CopyOnWriteArraySet () {al = new CopyOnWriteArrayList ();}

> the underlying layer of CopyOnWriteArraySet is implemented with CopyOnWriteArraySet. Variable operations (add,set,remove, etc.) need to copy the original array for operation, which is generally very expensive. Iterators support immutable operations such as hasNext () and netx (), but do not support mutable remove operations. Iterators are fast to use and do not conflict with other threads. When constructing iterators, they rely on immutable array snapshots.

CopyOnWriteArraySet multiline code demonstrates package com.rumenz.task;import java.util.List;import java.util.Set;import java.util.concurrent.*;// thread security public class CopyOnWrireArraySetExample {public static Integer clientTotal=5000; public static Integer threadTotal=200; private static Set set=new CopyOnWriteArraySet (); public static void main (String [] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool (); final Semaphore semaphore=new Semaphore (threadTotal); final CountDownLatch countDownLatch=new CountDownLatch (clientTotal) For (int I = 0; I

< clientTotal; i++) { final Integer j=i; executorService.execute(()->

{try {semaphore.acquire (); update (j); semaphore.release ();} catch (Exception e) {e.printStackTrace ();} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); System.out.println ("size:" + set.size ());} private static void update (Integer j) {set.add (j);}} / / size:5000CopyOnWriteArraySet usage scenarios

It is suitable for scenarios where the set size is generally very small and the read operation is much more than the write operation.

ConcurrentSkipListSetpublic ConcurrentSkipListSet () {m = new ConcurrentSkipListMap ();}

> ConcurrentSkipListSet is a new class added to jdk6. It supports natural sorting and is located in java.util.concurrent. ConcurrentSkipListSet is based on the Map collection, and the underlying layer is implemented by ConcurrentSkipListMap.

> in a multithreaded environment, the add,remove,contains of ConcurrentSkipListSet is thread-safe. However, for batch operations, addAll,removeAll,containsAll does not guarantee atomic operations, so it is not thread safe, because the underlying addAll,removeAll,containsAll calls the add,remove,contains method. In batch operations, each add,remove,contains can only be guaranteed to be atomic (that is, add,remove,contains is being carried out and will not be interrupted by other threads), but there is no guarantee that each batch operation will not be interrupted by other threads. So when addAll, removeAll, retainAll, and containsAll operate Additional synchronization operations need to be added.

Public boolean addAll (Collection c) {boolean modified = false; for (E e: C) if (add (e)) modified = true; return modified;} public boolean removeAll (Collection c) {Objects.requireNonNull (c); boolean modified = false; Iterator it = iterator () While (it.hasNext ()) {if (c.contains (it.next () {it.remove (); modified = true;}} return modified;} public boolean containsAll (Collection c) {for (Object e: C) if (! contains (e)) return false Return true;} ConcurrentSkipListSet code demonstrates package com.rumenz.task;import java.util.ArrayList;import java.util.List;import java.util.Set;import java.util.concurrent.*;// thread security public class CopyOnWrireArrayListExample {public static Integer clientTotal=5000; public static Integer threadTotal=200; private static Set set= new ConcurrentSkipListSet (); public static void main (String [] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool (); final Semaphore semaphore=new Semaphore (threadTotal) Final CountDownLatch countDownLatch=new CountDownLatch (clientTotal); for (int I = 0; I

< clientTotal; i++) { final Integer j=i; executorService.execute(()->

{try {semaphore.acquire (); update (j); semaphore.release ();} catch (Exception e) {e.printStackTrace ();} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); System.out.println ("size:" + set.size ());} private static void update (Integer r) {set.add (r);}} / / size:5000ConcurrentHashMap

> both key and value in ConcurrentHashMap do not allow a large number of optimizations for read operations for null,ConcurrentHashMap. It has an advantage in high concurrency scenarios.

> in a multithreaded environment, using HashMap for put operations will cause a dead loop, resulting in a CPU utilization of 100%. Therefore, HashMap cannot be used arbitrarily in a multithreaded environment. Cause analysis: when HashMap performs put, rehash expansion occurs when the inserted elements exceed the capacity. This operation will hash the original elements to a new expanded array. In the case of multithreading, if other threads are performing put operations at this time, if the hash values are the same, they may be represented by linked lists in the same array, resulting in a closed loop and a dead loop during get, so it is not thread safe.

> HashTable it is thread safe, it involves multithreaded operations to lock the entire table with the synchronized keyword, which means that all threads are competing for the same lock, which is safe in a multithreaded environment, but inefficient.

> HashTable has a lot of room for optimization. Such a rough method of locking the whole table can be soft in disguise. For example, in a multithreaded environment, when operating on different data sets, there is no need to compete for a lock at all, because they have different hash values and will not cause thread unsafety because of rehash, so they do not affect each other. This is lock separation technology, which reduces the granularity of locks and uses multiple locks to control multiple small table. When multiple threads access the data of different data segments in the container, there will be no lock competition between threads, which can effectively improve the efficiency of concurrent access, which is the core idea of the ConcurrentHashMapJDK1.7 version.

ConcurrentHashMap code demonstration case package com.rumenz.task;import java.util.Map;import java.util.Set;import java.util.concurrent.*;// thread security public class ConcurrentHashMapExample {public static Integer clientTotal=5000; public static Integer threadTotal=200; private static Map map=new ConcurrentHashMap (); public static void main (String [] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool (); final Semaphore semaphore=new Semaphore (threadTotal); final CountDownLatch countDownLatch=new CountDownLatch (clientTotal) For (int I = 0; I

< clientTotal; i++) { final Integer j=i; executorService.execute(()->

{try {semaphore.acquire (); update (j); semaphore.release ();} catch (Exception e) {e.printStackTrace ();} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); System.out.println ("size:" + map.size ());} private static void update (Integer j) {map.put (j, j);}} / / size:5000ConcurrentSkipListMap

> ConcurrentSkipListMap is implemented internally using SkipList structure. A jump list is a linked list, but the time complexity of inserting and reading data is O (log n) through a jump lookup.

> SkipList: using the space-for-time algorithm, each node in the linked list records not only the location of the next node, but also the subsequent level node according to the level level.

ConcurrentSkipListMap code case package com.rumenz.task;import java.util.Map;import java.util.concurrent.*;// thread safety public class ConcurrentSkipListMapExample {public static Integer clientTotal=5000; public static Integer threadTotal=200; private static Map map=new ConcurrentSkipListMap (); public static void main (String [] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool (); final Semaphore semaphore=new Semaphore (threadTotal); final CountDownLatch countDownLatch=new CountDownLatch (clientTotal); for (int I = 0; I

< clientTotal; i++) { final Integer j=i; executorService.execute(()->

{try {semaphore.acquire (); update (j); semaphore.release ();} catch (Exception e) {e.printStackTrace ();} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); System.out.println ("size:" + map.size ());} private static void update (Integer j) {map.put (j, j);} / / comparison between size:5000ConcurrentHashMap and ConcurrentSkipListMap

ConcurrentHashMap performs better than ConcurrentSkipListMap.

ConcurrentSkipListMap's key is ordered, and ConcurrentHashMap can't do it.

ConcurrentSkipListMap supports high concurrency, and its time complexity is log (N), which has nothing to do with the number of threads, that is, when the task is certain, the more concurrent threads are, the more advantages of ConcurrentSkipListMap can be realized.

The above is how to understand the Java concurrent container J.U.C. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report