10. Common auxiliary classes

10.1. CountDownLatch (counter)


In the official documents, the explanation of this block is complex. In short, this class is a subtraction counter, which is generally used to calculate the execution times of threads and execute an operation when it reaches 0.

For example, suppose there are six students in a class. Now after school, if the teacher wants to close the classroom door, he must wait until all six students have gone. Therefore, for each student, the total number of the remaining students is - 1. The teacher can't close the classroom door until all the students have gone.

Let's implement this case:

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        //Define the counter and count 6 times
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i < 7; i++) {
            new Thread(()-> {
                System.out.println(Thread.currentThread().getName()+"Student No. 1 came out of the classroom");
                countDownLatch.countDown(); //One student at a time, counter-1
            },String.valueOf(i)).start();
        }
        countDownLatch.await();     //When the counter is set to 0, execute the following program
        System.out.println("The teacher closed the door");
    }
}

Operation results:

Thus, we have completed this case. It can be seen that the function of CountDownLatch is to help us record the execution times of threads. Every time a thread runs, it calls the countDown() method to count - 1. When the count is 0, it wakes up the await() method to execute the following code; If it is not 0, it will be blocked all the time.

In CountDownLatch, we mainly remember these two methods:
  • countDown(); Count - 1
  • await(); Wait for the count to return to 0 before executing downward

10.2,CyclicBarrier


Similarly, with countdown latch, the official interpretation of this piece is also very abstract. In fact, simply put, this is an addition counter. After all, if the count has subtraction, there must be addition.

You can see that when creating a CyclicBarrier object, there are two overloads. The first overload has two parameters, which respectively mean int: record the number of threads, and Runnable: the thread to execute after reaching the number of times;

We use a case to show:

Suppose there are seven people ready to eat together, and the waiter will not serve until the seven people arrive

code implementation
public class CyclicBarrierDemo {
    public static void main(String[] args) {

        CyclicBarrier barrier = new CyclicBarrier(7, () -> {
            System.out.println("Serve the dish ");
        });
        for (int i = 1; i <= 7; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"Here comes the guest");
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

Operation results

It can be seen that each time a thread is run, the thread will wait and + 1 until all seven threads are executed, which will wake up the waiter thread passed in the created object for execution;

10.3 Semaphore


In short, Semaphore is designed to limit the number of threads; For example, there are six cars now, but there are only three parking spaces in the parking lot. Therefore, there must be three cars waiting outside to park when there are free parking spaces. When one or more of the vehicles are ready to leave, the parking space is released, and other vehicles can come in and park.

Case realization:

public class SemaphoreDemo {
    public static void main(String[] args) {
        //Set 3 parking spaces
        Semaphore semaphore = new Semaphore(3);

        //Create 6 threads to simulate 6 vehicles
        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();    //Occupied resources
                    System.out.println(Thread.currentThread().getName()+"Car No. parking, occupied parking space");
                    TimeUnit.SECONDS.sleep(2);  //Set delay to simulate occupied parking space
                    System.out.println(Thread.currentThread().getName()+"Car has left");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();    //Release resources
                }
            },String.valueOf(i)).start();
        }
    }
}

Operation results

It can be seen that the number of threads can be controlled by using Semaphore;

  • acquire(); Get the resource, the method will block until a resource is available
  • release(); Free resources.

Using this class for thread control can realize a current limiting operation, control the maximum number of threads, and ensure the safety of server hardware resources.

Keywords: Java Rust JUC

Added by daniellynn2000 on Wed, 15 Dec 2021 23:34:31 +0200