The Java.util.Concurrent (JUC) concurrent programming container package is available in Java 5.0, which adds utility classes commonly used in concurrent programming to define custom thread-like subsystems, including thread pools, asynchronous IO, and lightweight task frameworks. Collection implementations designed for use in multithreaded contexts are also provided

Let’s take the common list container as an example and do high pressure (high concurrency testing), using code and JMter testing tools to test thread safety separately

The demo making github.com/zhang-xiaox…

1: Use code to show the concurrent test results of the list container

package com.example.gaobinfa.common; import com.example.gaobinfa.annoations.NotThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; Public class ArrayListExample {/** * total requests */ public static int clientTotal = 5000; Public static int threadTotal = 200; public static int threadTotal = 200; private static List<Integer> list = new ArrayList<>(); 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 int count = i; executorService.execute(() -> { try { semaphore.acquire(); update(count); semaphore.release(); } catch (Exception e) { log.error("exception", e); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); / / may even throw exceptions Java. Lang. ArrayIndexOutOfBoundsException: 33 the info (" size: {} ", a list. The size ()); } private static void update(int i) { list.add(i); }}Copy the code

The results of the run are as follows (many tests also failed to reach the expected 5000)

Even throw exceptions

2: Use the Jmter test tool to test (we use the Web interface as the test, convenient to use Jmter)

Interface code

package com.example.gaobinfa.api; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; ** @author zhangxiaoxiang * @date: /** * CommonApi: 2019/08/11 */ @RestController @RequestMapping("/get") @Slf4j public class CommonApi { Integer i = 0; List<Integer> list = new ArrayList<>(); ** @requestMapping ("/ testarRayList ") public Object testarRayList () {list.add(I); i++; Log.info (" array length =" + list.size()); // Log.info (" array length =" + list.size()); Return "Array length =" + list.size(); }}Copy the code

Tool test debugging

 

Test results (still not up to 5000, inconsistent with expectations, thread unsafe)

Conclusion :List containers have security issues

Use concurrent containers to improve lists. The corresponding concurrent container is CopyOnWriteArrayList

1 Code Test

package com.example.gaobinfa.common.concurrent; import com.example.gaobinfa.annoations.ThreadSafe; import lombok.extern.slf4j.Slf4j; import java.util.List; import java.util.concurrent.*; @ Slf4j @ ThreadSafe public class CopyOnWriteArrayListExample {/ * * * * total request/public static int clientTotal = 5000; Public static int threadTotal = 200; public static int threadTotal = 200; private static List<Integer> 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 int count = i; executorService.execute(() -> { try { semaphore.acquire(); update(count); semaphore.release(); } catch (Exception e) { log.error("exception", e); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("size:{}", list.size()); } private static void update(int i) { list.add(i); }}Copy the code

Run results (multiple tests)

2JMter tool testing

 

package com.example.gaobinfa.api; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * ConcurrentApi: Test JUC concurrent container with improved test ** @author zhangxiaoxiang * @date: 2019/08/11 */ @RestController @RequestMapping("/get") @Slf4j public class ConcurrentApi { Integer i = 0; List<Integer> list = new CopyOnWriteArrayList<>(); ** @requestMapping ("/ copyonWritearRayList ") public Object testArrayList() { list.add(i); i++; Log.info (" array length improved with concurrent collection JUC =" + list.size()); Return "use concurrent collection JUC to improve array length =" + list.size(); }}Copy the code

Tool (multiple) test results

 

This is as expected, thread-safe, other operations like map collection and so on, my file structure