CountDownLatch是什么?如何使用?

概述:

CountDownLatch(计数器)是一个用于多线程同步的 Java 工具。它允许一个或多个线程等待,直到其他线程完成任务或是事件的发生。CountDownLatch 通常用于协调多个线程之间的同步,以便一个线程等待另一个线程完成某项任务后再继续执行。

CountDownLatch 本质上是一个计数器,用于记录需要等待的线程数量。当一个线程完成任务时,它会通知 CountDownLatch 计数器减一。当计数器的值减为零时,等待的线程将被释放,可以继续执行下面的任务。

使用 CountDownLatch 可以通过调用 await() 方法来阻塞当前线程,等待其他线程完成任务。当需要等待的线程数量减少时,可以调用 countDown() 方法通知 CountDownLatch 计数器减一。当计数器的值减为零时,等待的线程将被释放。

要使用CountDownLatch,首先需要创建一个CountDownLatch对象,然后在线程中调用countDown()方法来通知CountDownLatch计数器减1。当计数器的值变为0时,等待在CountDownLatch上的线程就会被唤醒。

CountDownLatch latch = new CountDownLatch(1);
// ...
latch.await(); // 等待计数降到0

使用示例1

mport java.util.concurrent.CountDownLatch;  
  
public class CountDownLatchExample {
    
      
    public static void main(String[] args) throws InterruptedException {
    
      
        int countDownValue = 3;  
        CountDownLatch latch = new CountDownLatch(countDownValue);  
  
        // 创建三个线程来执行任务  
        Thread thread1 = new Thread(() -> {
    
      
            latch.countDown(); // 通知计数器减1  
            System.out.println("Thread 1 完成");  
        });  
        Thread thread2 = new Thread(() -> {
    
      
            latch.countDown(); // 通知计数器减1  
            System.out.println("Thread 2 完成");  
        });  
        Thread thread3 = new Thread(() -> {
    
      
            latch.countDown(); // 通知计数器减1  
            System.out.println("Thread 3 完成");  
        });  
  
        // 启动线程  
        thread1.start();  
        thread2.start();  
        thread3.start();  
  
        // 等待所有线程执行完毕  
        latch.await(); // 在这里等待,直到计数器的值变为0  
  
        // 所有线程已经执行完毕,继续执行下面的任务  
        System.out.println("所有 threads 完成");  
    }  
}

在上面的示例中,我们创建了一个CountDownLatch对象,并将其初始化为3。然后我们创建了三个线程来执行任务,并在每个线程中调用countDown()方法来通知计数器减1。最后,在主线程中,我们使用await()方法等待所有线程执行完毕,然后继续执行下面的任务。

使用示例2

使用线程池生成100*300个Redis 全局ID

@SpringBootTest
@RunWith(SpringRunner.class)
public class AppTest {
    
    

    @Resource
    private RedisWorker redisWorker;

    private ExecutorService es = Executors.newFixedThreadPool(100);

    @Test
    public void testNextId() throws InterruptedException {
    
    

        CountDownLatch latch = new CountDownLatch(300);

        Runnable task = () -> {
    
    
            for (int j = 0; j < 100; j++) {
    
    
                System.out.println("id========" + redisWorker.nextId("order"));
            }
            latch.countDown(); //通知计数器减1  
        };

        long begin = System.currentTimeMillis();
        for (int i = 0; i < 300; i++) {
    
    
            es.submit(task);
        }

        latch.wait();  // 在这里等待,直到计数器的值变为0  
        long end = System.currentTimeMillis();
        //记录完成时间
        System.out.println("time===" + (end - begin));

    }
}
@Component
public class RedisWorker {
    
    

    //开始时间错
    private final static long BEGIN_TIMESTAMP = 1640995200l;
    //序列号位数
    private final static long COUNT_BITS = 32;
    @Autowired
    private StringRedisTemplate redisTemplate;

    public long nextId(String keyPre){
    
    
        // 1 生成时间错
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;
        // 2 生成序列号
        // 2.1 获取date,便于获得一天的订单
        String date = now.format(DateTimeFormatter.ofPattern("yyyyMmdd"));
        // 2.2 自增长
        Long count = redisTemplate.opsForValue().increment("icr:" + keyPre + ":" + date);

        // 3 拼接并返回
        return timestamp << COUNT_BITS | count;
    }
}

源码下载:

https://gitee.com/charlinchenlin/koo-erp

猜你喜欢

转载自blog.csdn.net/lovoo/article/details/130855731