JAVA simulates instantaneous high concurrency

I received an interview call a few days ago. I was very impressed with the interview content. How to simulate a concurrency? At that time, although my answer could be considered correct, I felt that I lacked practical details and only had a general description.

      At that time my answer was: "All threads wait on the same node, and then notifyAll on a certain node."

      Interviewer: "Have you heard of the shocking herd effect?"

      Me: "I haven't heard this term, but I know that waking up all threads instantly will increase the CPU load instantly."

      Interviewer: "Then do you have any way to improve?"

      Me: "Using blocking technology, block all threads at a certain node, and open blocking when the number of threads reaches a certain number using conditions."

      The interviewer seemed satisfied and ended the topic.

      After the interview, I turned back to this block and thought, how to block it? My first idea is to use AtoInteger to calculate the number of threads, then use the synchronize method block to block a thread, and execute sleep according to the judgment of AtoInteger.

      code show as below:

 

/**
* Created with IntelliJ IDEA.
* User: 菜鸟大明
* Date: 14-10-21
* Time: 下午4:34
* To change this template use File | Settings | File Templates.
*/
public class CountDownLatchTest1 implements Runnable{
final AtomicInteger number = new AtomicInteger();
volatile boolean bol = false;

@Override
public void run() {
System.out.println(number.getAndIncrement());
synchronized (this) {
try {
if (!bol) {
System.out.println(bol);
bol = true;
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("并发数量为" + number.intValue());
}

}

public static void main(String[] args) {
ExecutorService pool = Executors. newCachedThreadPool();
CountDownLatchTest1 test = new CountDownLatchTest1();
for (int i=0;i<10;i++) {
pool.execute(test);
}
}
}

 

  The result is:

 

0
2
1
4
3
false
5
6
7
8
9
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10
Concurrent quantity is 10

 

From the results, it should be possible to solve the problem. Using synchronization locks, volatile solves the problem of simultaneous release. The difficulty lies in the switch.

Later, I searched for information and found a CountDownLatch class, which specializes in this.

CountDownLatch is a synchronization auxiliary class, just like a countdown counter. When creating an object, set the initial value through the constructor. Call the await() method of the CountDownLatch object to be in a waiting state. Call the countDown() method to decrement the counter by 1. When the count reaches 0 , all waiters or a single waiter starts executing.

 

The constructor parameter specifies the number of times to count

 

new CountDownLatch(1)

 

countDown method, the current thread calls this method, the count is decremented by one
new CountDownLatch(1)

 

await method, calling this method will block the current thread until the timer value is 0
cdOrder.await();  

  

a Directly paste the code, reproduce the code
/**
 *
 * @author Administrator
 *This program is used to simulate sending and executing commands. The main thread represents the commander, and 3 new threads represent the soldiers. The soldiers have been waiting for the commander to issue an order.
 *If the commander does not issue an order, The soldiers must wait. Once the order is issued, the soldiers all go to perform their tasks, the commander is in a waiting state, the soldiers report to the
 * commander when the task is completed, and the commander ends the waiting.
 */
public class CountdownLatchTest {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool(); //Create a thread pool
        final CountDownLatch cdOrder = new CountDownLatch(1);//Commander's command, set to 1, commander When the command is reached, cutDown becomes 0, and the soldiers perform the task
        final CountDownLatch cdAnswer = new CountDownLatch(3);//Because there are three warriors, the initial value is 3. After each warrior performs the task, cutDown once, when three After all executions are completed and it becomes 0, the commander stops waiting.
        for(int i=0;i<3;i++){
            Runnable runnable = new Runnable(){
                public void run(){
                    try {
                        System.out.println("Thread" + Thread.currentThread().getName() +
                                "Ready to accept orders");
                        cdOrder.await(); //The soldiers are all waiting for orders
                        System.out.println("Thread" + Thread.currentThread().getName() +
                                "Command accepted");
                        Thread.sleep((long)(Math.random()*10000));
                        System.out.println ("Thread" + Thread.currentThread().getName() +
                                "Response command processing result");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        cdAnswer.countDown(); //The task is completed, return to the commander, and cdAnswer is reduced by 1.
                    }
                }
            };
            service.execute(runnable);//Add tasks to the thread pool
        }
        try {
            Thread.sleep((long)(Math.random()*10000));
            System.out.println("Thread" + Thread.currentThread().getName() +
                    "Command to be issued soon");
            cdOrder.countDown(); //Send the command, cdOrder is reduced by 1, and the waiting soldiers stop waiting for the transfer to perform the task.
            System.out.println("Thread" + Thread.currentThread().getName() +
                    "Command sent, waiting for result");
            cdAnswer.await(); //The commander is in a waiting state after the command is sent, once cdAnswer When it is 0, stop waiting and continue to execute
            System.out.println("Thread" + Thread.currentThread().getName() +
                    "All response results have been received");
        } catch (Exception e) {
            e.printStackTrace( );
        } finally {
        }
        service.shutdown(); //The task ends, stop all threads in the thread pool
    }
}

  Results of the:

 

Thread pool-1-thread-2 is preparing to accept a command
Thread pool-1-thread-3 is preparing to accept a command
Thread pool-1-thread-1 is preparing to accept a command
Thread main is about to issue a command
Thread pool-1-thread-2 has Command accepted
Thread pool-1-thread-3 has accepted command
Thread pool-1-thread-1 has accepted command
Thread main has sent command and is waiting for result
Thread pool-1-thread-2 responds to command processing result
Thread pool-1- thread-1 responds to command processing results
thread pool-1-thread-3 responds to command processing results
thread main has received all response results

 

The above is also an implementation method. The await() method of countDownLatch is used to replace the blocking function of synchronize and sleep, and the countDown method is used as a switch and a way to calculate the number of threads.

If there is a difference, the latter is definitely better, because the first method relies on sleep(xxx) to block and it is not easy to grasp the shortest time. If it is too short, the switch may be turned on before reaching the fixed number of threads.

As for the difference in performance between the two, I don't know yet, and I have the opportunity to test it.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326208934&siteId=291194637