Original statement: this article comes from the public number “fat rolling pig learning programming”, please indicate the source of reprint.
In the last section, we talked about the three Bug sources of concurrent programming in JAVA. This has not even started to enter the world of concurrency, but it runs into problems.
The conundrum is one that all beginners have: there is no way to reproduce the bugs that theoretical knowledge tells us. But practice is important, so how do you simulate concurrency in a local development environment?
Simulation concurrency tools complete
There are many ways to simulate a concurrent environment locally, and the most popular ones are the following, including tools and code:
Postman: Http request simulation tool, can be set to launch N requests (but not recommended, not professional)
Apache Bench (AB) : Apache Bench (AB) is a web stress test tool for The Apache server. It is a command line tool that can create many concurrent access threads according to the command, and simulate multiple visitors to a certain URL at the same time. In general, THE AB tool is small and simple, fast to learn, and can provide the required basic performance indicators. But the disadvantage is that there is no graphical results, can not monitor.
Apache JMeter: Java-based stress testing tool developed by the Apache organization. The functionality will be more powerful than AB, especially with the GUI graphical interface, which is cool. Jmeter is a complete request and return; AB just makes the request and does not process the return. If you want to see results returned, you should also select JMeter.
4. JAVA code: including CountDownLatch, CyclicBarrier, etc
We’ll focus on how to simulate a concurrent environment with JMeter and code, and recommend using both.
CountDownLatch(Waiting for multiple threads to complete)
Original statement: this article comes from the public number “fat rolling pig learning programming”, please indicate the source of reprint.
CountDownLatch was introduced in Java 1.5 and exists under the java.util.cucurrent package.
This class enables a thread to wait for other threads to complete their respective executions before executing.
It is implemented with a counter whose initial value is the number of threads. Each time a thread completes, the counter has a value of -1. When the counter has a value of 0, it indicates that all threads have completed, and the threads waiting on the lock can resume work.
As shown in the figure, Thread A is blocked because it is awaiting the await method with an initial value of CNT =3. Thread T1\T2\T3 calls countDown and decrement the counter by one. Thread A does not resume running until CNT =0. In other words, Thread A waits for the other three threads to complete before executing:
Only one constructor is provided in the countDownLatch class:
Public CountDownLatch(int count) {}; There are three most important methods in the countDownLatch class:Copy the code
// The thread calling the await() method is suspended and waits until count is 0 before continuing
public void await() throws InterruptedException { }; // Similar to await(), Public Boolean await(long timeout, TimeUnit Unit) throws InterruptedException {}; Public void countDown() {};Copy the code
For example: The requirement is to process an Excel, which has many rows of data. For efficiency, we can use multi-threading, but after processing all rows of data, we need to notify the main thread. If there was no countDownLatch, the effect would look something like this:
If countDownLatch is added to the main thread and the await() method is called, the main thread is suspended and waits until count is 0 before continuing:
static CountDownLatch countDownLatch = new CountDownLatch(100); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 100; i++) { Thread thread = new Thread(() -> { doWork(); countDownLatch.countDown(); }); thread.start(); } countDownLatch.await(); System.out.println(" End time to process whole Excel "+ system.currentTimemillis ()); } public static void doWork(){system.out.println (" "+ system.currentTimemillis ()); }Copy the code
Thread thread = new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
doWork();
});
thread.start();
countDownLatch.countDown();Copy the code
The thread pool
ExecutorService executorService = new ThreadPoolExecutor(100, 200, 60, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(20000), new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r); }});Copy the code
CyclicBarrier
Original statement: this article comes from the public number “fat rolling pig learning programming”, please indicate the source of reprint.
CyclicBarrier literally means CyclicBarrier. What it does is allow a group of threads to block when they reach a barrier (also known as a synchronization point), and the barrier will not open until the last thread reaches the barrier, and all threads blocked by the barrier will continue to work.
As shown in the figure below, there are four threads A, B, C, and D, which may arrive at the barrier in different order. When A, B and C arrive at the fence, they do not meet the requirement of total number [4], so they will wait for A long time. When thread D arrives, the fence will release.
CyclicBarrier constructor
Public CyclicBarrier(int parties) public CyclicBarrier(int parties, Runnable barrierAction)Copy the code
The main methods are as follows
// The thread calling the await method tells the CyclicBarrier that it has reached the synchronization point and the current thread is blocked. The blocking thread will not execute until the parties participating threads call the await method. Public int await() public int await(long timeout, TimeUnit unit) public void reset()Copy the code
Based on this feature, we can also simulate concurrent execution. The following code simulates concurrent execution of 5 threads:
private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5); public static void main(String[] args) throws InterruptedException { ExecutorService executorService = ExecutorServiceUtils.getExecutor(); for (int i = 0; i < 20; i++) { int finalI = i; Thread.sleep(1000); executorService.submit(() -> { try { doWork(finalI); } catch (Exception e) { e.printStackTrace(); }}); / / through print log. It has the function of automatic reset the log info (" Parties = {} {} in the waiting ", cyclicBarrier. GetParties (), cyclicBarrier. GetNumberWaiting ()); } executorService.shutdown(); } public static void doWork(Integer threadNum) throws Exception { Thread.sleep(1000); log.info("{} is ready", threadNum); cyclicBarrier.await(); log.info("{} continue", threadNum); }Copy the code
The main differences between CountDownLatch and CyclicBarrier:
1. CountDownLatch is mainly used to solve the situation where one thread waits for multiple threads, which can be analogous to the leader of a tour group waiting for all the tourists to arrive before moving to the next spot.
CyclicBarrier, on the other hand, is a group of threads waiting for each other, more like a bunch of traveling buddies.
2. CountDownLatch is a minus count and CyclicBarrier is a plus count.
3. The CountDownLatch counter is not recycled, which means that once the counter drops to 0 and another thread calls await(), it will pass directly.
But CyclicBarrier counters are recyclable and automatically reset to your original value once the counter drops to zero.
CyclicBarrier also has the ability to set callback functions. CountDownLatch does not support the callback function.
Ok, now go back to the beginning of the code that can’t be repeated, let’s use a CyclicBarrier, and you can see that 0 happens.
Another point to mention: even if it is true concurrent execution, the problem is still a small probability of the event, I test run 15 times before the result of 0. If you’re unlucky, you might run it 100 times and still not see it. Don’t worry too much about it!
JMeter tool
1. Decompress the directory, configure environment variables, and run jmeter.bat
Add a thread group:
Set the number of concurrent threads to 50. No loop is required after each thread is executed:
Add HTTP requests, such as the one we want to test /test:
Configure HTTP IP/port/encoding format, etc. :
Add two listeners to view the graph result and the number of results after execution:
6, run the thread group, can output our results
Well, that’s all for today, and it’s time to say goodbye to everyone
Original statement: this article comes from the public number “fat rolling pig learning programming”, please indicate the source of reprint.
This article is reprinted from the public number [fat rolling pig learning programming] programming with comics so easy and interesting! Welcome to pay attention!