A brief use of CountDownLatch and insert Enum

260 阅读2分钟

A brief use of CountDownLatch and insert Enum

1.Concept:

CountDownLatch maintains a counter internally, and only when the counter = 0 does some threads stop blocking and start executing.

2.Basic method:

CountDownLatch has two main methods

countDown () to make the counter -1, and await () to make the thread block. When count = = 0, the blocking thread wakes up automatically.

3.give an example:

When we break through the level to fight monsters, we must fight all the monsters to win.

And that's when we can imitate a Queue,

[1].case1:When CountDownLatch is not used in a multithreaded environment

code:

public class CountDownLatchDemo {
    public static void main(String[] args) {
        slayMonsters();
    }

    public static void slayMonsters(){
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println("Monster "+Thread.currentThread().getName()+" has been slain");
            },String.valueOf(i)).start();
        }

        System.out.println("You have slain all monsters,bravo!");
    }
}

result:

Monster 1 has been slain
Monster 5 has been slain
Monster 4 has been slain
You have slain all monsters,bravo!
Monster 2 has been slain
Monster 3 has been slain
Monster 0 has been slain

And then we'll find out. The main thread will finish before some of other threads,It's like when you break through the level, you have a total of six monsters, but you can only fight two or three to win a victory. This is unreasonable.

We can also optimize it before we want to go to CountDownLatch.

code:

public static void slayMonsters(){
        for (int i = 0; i < COUNT; i++) {
            new Thread(()->{
                System.out.println("Monster "+Thread.currentThread().getName()+" has been slain");
            },String.valueOf(i)).start();
        }
		// Gives execution of the main thread to another thread
		while (Thread.activeCount()>2){
            Thread.yield();
        }
        System.out.println("You have slain all monsters,bravo!");
    }
}

result:

Monster 0 has been slain
Monster 2 has been slain
Monster 1 has been slain
Monster 5 has been slain
Monster 4 has been slain
Monster 3 has been slain
You have slain all monsters,bravo!

And that's when we find out. The main thread does not execute until the other threads have finished executing. This result is correct.

[2].case2:Next we will use CountDownLatch in our code.

	public static final int COUNT=6;

    public static void slayMonsters(){
        CountDownLatch countDownLatch=new CountDownLatch(COUNT);
        for (int i = 0; i < COUNT; i++) {
            new Thread(()->{
                //decrement by 1 after the thread completes execution
                countDownLatch.countDown();
                System.out.println("Monster "+Thread.currentThread().getName()+" has been slain");
            },String.valueOf(i)).start();
        }

		try {
            //When the value in CounyDownLatch is 0, it will execute Main Thread and Code
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("You have slain all mo, s,bravo!");
    }

result:

Monster 0 has been slain
Monster 2 has been slain
Monster 1 has been slain
Monster 5 has been slain
Monster 4 has been slain
Monster 3 has been slain
You have slain all monsters,bravo!

The result was as expected.

But in some cases, we want to change the name of our threads to us., the name we defined. At this time, many people will think of using if to make a loop decision. This method is feasible, but inefficient.

In this case, we can solve the problem by using an enumeration class, it's the equivalent of a small database in Java.(enumeration was come out after the version 1.5 of JDK release)

4.Using Enumeration Types in Multiple Threads

code:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Getter
public enum Monster {

    ONE(0,"teddy"),TWO(1,"zombie"),THREE(2,"bird queen"),FOUR(3,"black widow"),FIVE(4,"Hydra"),SIX(5,"Siren");
    
    private int mNo;
    private String mName;
    
    public static Monster forEach_Monster(int index){
        //enumerate the data
        Monster[] monsters = Monster.values();
        for (Monster monster : monsters) {
            if(monster.getMNo()==index){
                return monster;
            }
        }
        return null;
    }
}

Modify the previous code:

public static void slayMonsters(){
        for (int i = 0; i < COUNT; i++) {
            new Thread(()->{
                System.out.println("Monster "+Thread.currentThread().getName()+" has been slain");
            },Monster.forEach_Monster(i).getMName()).start();
        }

        System.out.println("You have slain all monsters,bravo!");
    }

We can get result

Monster teddy has been slain
Monster Hydra has been slain
Monster black widow has been slain
Monster bird queen has been slain
Monster zombie has been slain
Monster Siren has been slain
You have slain all monsters,bravo!

Using enumerations can make data more flexible, but when you need to change data, you only need to change the data that is in enumerations.

summary:

The above is my CountDownLatch in Java multithreading. And enumerated types.

If you like it, leave me a like or comments below.