Author: When you come back link: www.cnblogs.com/yougewe

Sometimes you need to test the concurrency performance of a function, and don’t want to use other tools, just your own development language, to make a concurrent request is the most convenient.

Java simulation of concurrent requests, naturally is very convenient, as long as a few threads, initiated a request. However, this kind of request, generally there will be a start order, not really concurrent!

How do you really do concurrent concurrency?

CountDownLatch is the point of this article. Java provides CountDownLatch, which is perfect for this purpose.

Only need to:

  1. Open n threads, add a lock, open all threads;

  2. When all threads are ready, press the Open button and you can actually initiate a concurrent request.

package com.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.CountDownLatch; public class LatchTest { public static void main(String[] args) throws InterruptedException { Runnable taskTemp = new Runnable() {// Note that this is not thread-safe, leaving a pit private int iCounter; @Override public void run() { for(int i = 0; i < 10; I++) {/ / a request / / HttpClientOp doGet (" https://www.baidu.com/ "); iCounter++; System.out.println(System.nanoTime() + " [" + Thread.currentThread().getName() + "] iCounter = " + iCounter); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }}}}; LatchTest latchTest = new LatchTest(); latchTest.startTaskAllInOnce(5, taskTemp); } public long startTaskAllInOnce(int threadNums, final Runnable task) throws InterruptedException { final CountDownLatch startGate = new CountDownLatch(1); final CountDownLatch endGate = new CountDownLatch(threadNums); for(int i = 0; i < threadNums; I++) {Thread t = new Thread() {public void run() {try { try { task.run(); CountDown (); // countDown(); // countDown(); } } catch (InterruptedException ie) { ie.printStackTrace(); }}}; t.start(); } long startTime = System.nanoTime(); System.out.println(startTime + " [" + Thread.currentThread() + "] All thread is ready, concurrent going..." ); CountDown (); countDown(countDown); countDown(countDown); // etc end door open endgate.await (); long endTime = System.nanoTime(); System.out.println(endTime + " [" + Thread.currentThread() + "] All thread is completed."); return endTime - startTime; }}Copy the code

The execution effect is shown in the figure below:

HttpClientOp tool class, you can use a mature toolkit, or you can write a brief access method, refer to the following:

class HttpClientOp { public static String doGet(String httpurl) { HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; String result = null; // Create a remote URL connection object URL = new URL(httpurl); Connection = (httpURLConnection) url.openConnection(); / / set up the connection way: get connection. SetRequestMethod (" get "); / / set the connection between a host server timeout: 15000 milliseconds connection. SetConnectTimeout (15000); / / set the remote data returned by the read time: 60000 milliseconds connection. SetReadTimeout (60000); // Send a request connection.connect(); / / to connect the connection, get the input stream the if (connection. The getResponseCode () = = 200) {is = connection. GetInputStream (); // encapsulate input stream is and specify character set br = new InputStreamReader(is, "utF-8 "); SBF = new StringBuffer(); String temp = null; while ((temp = br.readLine()) ! = null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally {// Close the resource if (null! = br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null ! = is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } connection.disconnect(); } return result; } public static String doPost(String httpUrl, String param) { HttpURLConnection connection = null; InputStream is = null; OutputStream os = null; BufferedReader br = null; String result = null; try { URL url = new URL(httpUrl); Connection = (HttpURLConnection) url.openConnection(); / / set the connection request mode connection. SetRequestMethod (" POST "); / / set up the connection between a host server timeout: 15000 milliseconds connection. SetConnectTimeout (15000); / / read the host server return data timeout: 60000 milliseconds connection. SetReadTimeout (60000); // The default value is false. When sending/writing data to a remote server, set this value to true connection.setdoOutput (true); // The default value is true, which is set to true when reading data from the remote service. This parameter is optional. // Format the parameters passed in: the request parameters should be of the form name1=value1&name2=value2. connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // Set the Authorization information: Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0 connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0"); / / through connection object access to an output stream OS = connection. GetOutputStream (); Os.write (param.getBytes())); // Write/transfer arguments through the output stream object, os.write(param.getbytes ()); / / through the connection object to obtain an input stream, to the remote reading the if (connection. The getResponseCode () = = 200) {is = connection. GetInputStream (); Br = new InputStreamReader(is, "UTF-8"); br = new InputStreamReader(is, "UTF-8") StringBuffer sbf = new StringBuffer(); String temp = null; While ((temp = br.readline ())! = null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally {// Close the resource if (null! = br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null ! = os) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if (null ! = is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); // Disconnect connection.disconnect(); } return result; }}Copy the code

As above, you can make a true concurrent request.

The operation flow diagram of concurrent request is as follows:

A gate is set up to ensure that all threads work at the same time. However, simultaneous initiation here is only a linguistic aspect of things, and it is not absolute concurrency. The specific call depends on the number of cpus, the number of threads and the operating system’s thread scheduling function, but we don’t need to worry about these, the key is to understand the principle!

Similar to CountDownLatch, CyclicBarrier provides the same effect by waiting for all threads to arrive at a certain point before starting an action. However, the purpose of a CyclicBarrier is purely to wait for all threads to arrive. Although CountDownLatch is implemented after all threads arrive, its trigger point is actually the last switch, so the focus is different.

Let’s take a quick look at how a fence can achieve true concurrency. The following is an example:

Public class LatchTest {public static void main(String[] args) throws InterruptedException {Runnable taskTemp = new Runnable() { private int iCounter; @override public void run() {// make a request // httpclientop.doget ("https://www.baidu.com/"); iCounter++; System.out.println(System.nanoTime() + " [" + Thread.currentThread().getName() + "] iCounter = " + iCounter); }}; LatchTest latchTest = new LatchTest(); // latchTest.startTaskAllInOnce(5, taskTemp); latchTest.startNThreadsByBarrier(5, taskTemp); } public void startNThreadsByBarrier(int threadNums, Runnable finishTask) throws InterruptedException { CyclicBarrier barrier = new CyclicBarrier(threadNums, finishTask); For (int I = 0; int I = 0; i < threadNums; i++) { Thread.sleep(100); new Thread(new CounterTask(barrier)).start(); } System.out.println(Thread.currentThread().getName() + " out over..." ); }} class CyclicBarrier implements Runnable {// CyclicBarrier implements Runnable; public CounterTask(final CyclicBarrier barrier) { this.barrier = barrier; } public void run() { System.out.println(Thread.currentThread().getName() + " - " + System.currentTimeMillis() + " is ready..." ); Try {// set the barrier so that the waiting thread opens the barrier. Await (); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " - " + System.currentTimeMillis() + " started..." ); }}Copy the code

Its running results are shown as follows:

Each has its own application scenarios, but the key is the need. For the purposes of the examples in this article, individuals would prefer to use locking because it is more controllable. But the code is much, so see you like it!

Recent hot articles recommended:

1.1,000+ Java Interview Questions and Answers (2021)

2. Don’t use if/ else on full screen again, try strategy mode, it smells good!!

3. Oh, my gosh! What new syntax is xx ≠ null in Java?

4.Spring Boot 2.5 is a blockbuster release, and dark mode is exploding!

5. “Java Development Manual (Songshan version)” the latest release, quick download!

Feel good, don’t forget to click on + forward oh!