CountDownLatch和Semaphore使用场景

本文介绍了Java中CountDownLatch和Semaphore的功能及应用场景。CountDownLatch可实现计数器功能,让任务等待其他任务完成后执行;Semaphore是信号量,能阻塞线程并控制同时访问线程的个数,适合控制并发数。两者结合使用效果更佳,还可用于流量分流。

CountDownLatch

CountDownLatch位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等到其它3任务完成才能执行,此时就可以用CountDownLatch来实现。

img

假设计数器的值为2,线程A调用await()方法之后,A线程就进入了等待状态,之后其它线程中执行countDown(),计数器就会-1,该操作线程继续执行,当计数器从2编程0,线程A继续执行。

package com.keytech.task;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;


class TaskApplicationTests {
    //目标:炒菜
    //1.洗菜 5秒
    //2.买盐 3秒
    public static void main(String[] args) throws InterruptedException {
        Executor executor=Executors.newFixedThreadPool(2);
        CountDownLatch countDownLatch=new CountDownLatch(2);
        long now = System.currentTimeMillis();
        //洗菜5秒
        executor.execute(()->{
             try{
                 Thread.sleep(5000);

             }catch (Exception e){
                 e.printStackTrace();
             }finally {
                 if(countDownLatch!=null){
                     countDownLatch.countDown();
                 }
             }
        });
        //买盐3秒
        executor.execute(()->{
             try{
                 Thread.sleep(3000);
             }catch (Exception e){
                e.printStackTrace();
             }finally {
                 if(countDownLatch!=null){
                     countDownLatch.countDown();
                 }
             }
        });
        countDownLatch.await();
        System.out.println("可以炒菜了"+(System.currentTimeMillis()-now));
    }
}

//可以炒菜了5082

Semaphore

image-20201226194300986

Semaphore就是信号量,Semaphore可以阻塞线程并且可以控制同时访问线程的个数,通过acquire()获取一个许可,如果没有获取到就继续等待,通过release()释放一个许可。Semaphore和锁有点类似,都可以控制对某个资源的访问权限。

CountDownLatchSemaphore通常和线程池配合使用。Semaphore适合控制并发数,CountDownLatch比较适合保证线程执行完后再执行其他处理,因此模拟并发时,使用两者结合起来是最好的。

Semaphore可以用来做流量分流,特别是对公共资源有限的场景,比如数据库连接。
假设有这个的需求,读取几万个文件的数据到数据库中,由于文件读取是IO密集型任务,可以启动几十个线程并发读取,但是数据库连接数只有10个,这时就必须控制最多只有10个线程能够拿到数据库连接进行操作。这个时候,就可以使用Semaphore做流量控制。

package com.keytech.task;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * @className: SemaphoreTest
 * @description: TODO 类描述
 * @author: mac
 * @date: 2020/12/26
 **/
public class SemaphoreTest {
    public static void main(String[] args) {
        ExecutorService  executor=Executors.newFixedThreadPool(40);

        Semaphore  semaphore=new Semaphore(10);
        for (int i = 0; i < 40; i++) {
            executor.execute(()->{
                try {
                    semaphore.acquire();
                    System.out.println("处理数据中......");
                    Thread.sleep(3000);
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            });
        }
        executor.shutdown();

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值