JUC常用辅助类及读写锁

JUC常用辅助类*

(1).CountDownLatch

手动减

/**
 * CountDownLatch减法计数器
 */
public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);//设定计数器原始值
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"->");
                countDownLatch.countDown();//计数器做减法
            },i+"").start();
        }
        countDownLatch.await();//等待计数器为0后执行之后操作
        System.out.println("归零");
    }
}
0->
2->
3->
1->
4->
5->
归零

(2).CyclicBarrier

自动加

/**
 * CyclicBarrierTest加法计数器
 */
public class CyclicBarrierTest {
    public static void main(String[] args) {
        //需要达到的已执行线程数    达到后执行的指定线程
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("达到了");
        });
        for (int i = 1; i < 10; i++) {
            final int a = i; //λ表达式是取不到这个i的
            new Thread(()->{
                System.out.println("->"+a);
                //执行计数器等待 每次执行一个线程 自动 加
                try {
                    cyclicBarrier.await();//等待达到
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
->2
->6
->5
->4
->3
->1
->9
达到了
->8
->7

(3).Semaphore

信号量(可同时执行量)

public class SemaphoreTest {
    public static void main(String[] args) {
        //指定由几个位置(几个可同时执行的线程)
        Semaphore semaphore = new Semaphore(2);
        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();//让这个线程得到一个位置
                    System.out.println(Thread.currentThread().getName()+"在执行");
                    TimeUnit.SECONDS.sleep(3);//模拟线程执行3秒
                    System.out.println(Thread.currentThread().getName()+"在执行完毕");
                    semaphore.release();//释放当前位置 唤醒其他线程并给予位置
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },i+"").start();
        }
    }
}
1在执行
2在执行   //3s
1执行完毕
2执行完毕
4在执行
3在执行   //3s
4执行完毕
3执行完毕
5在执行
6在执行   //3s
6执行完毕
5执行完毕

使用场景:多个资源互斥 并发限流,控制最大线程数

读写锁

ReadWriteLock -实现类-> ReentrantReadWriteLock

多个线程 同时可读 但 只能单线程 单线写入

应用场景: 写入时只能由一条线程写入 且不能被读取 , 读取时随意

public class ReadWriteLockTest {
    public static void main(String[] args) {
        MyRw myRw = new MyRw();
        //执行写
        for (int i = 0; i < 10; i++) {
            final int ii = i;
            new Thread(()->{myRw.writeM(ii+"","写入的内容"+ii);},ii+"").start();
        }
        //执行读
        for (int i = 0; i < 10; i++) {
            final int ii = i;
            new Thread(()->{myRw.readM(ii+"");},ii+"").start();
        }
    }
}
/**
 * 读写方法
 */
class MyRw{
    private volatile Map<String,Object> map = new HashMap<>();
    //获取读写锁 使用方式基本和 lock相似
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    /**
     * 写入方法
     * @param key
     * @param value
     */
    public void writeM(String key,String value){
        readWriteLock.writeLock().lock();//加写锁 
        try {//业务
            System.out.println(key+"写入中");
            map.put(key,value);
            System.out.println(key+"写入成功");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();//解锁
        }
    }

    /**
     * 读取方法
     * @param key
     */
    public void readM(String key){
        readWriteLock.readLock().lock();//加读锁
        try {//业务
            System.out.println(key+"读取中");
            System.out.println(map.get(key));
            System.out.println(key+"读取成功");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();//解锁
        }
    }

}
0写入中
0写入成功
3写入中
3写入成功
8写入中
8写入成功
2写入中
2写入成功
1写入中
1写入成功
5写入中
5写入成功
7写入中
7写入成功
6写入中
6写入成功
4写入中
4写入成功
9写入中
9写入成功
2读取中
0读取中
写入的内容0
0读取成功
6读取中
写入的内容6
6读取成功
4读取中
写入的内容4
4读取成功
写入的内容2
2读取成功
9读取中
8读取中
写入的内容8
8读取成功
5读取中
写入的内容5
5读取成功
7读取中
写入的内容7
7读取成功
1读取中
写入的内容1
1读取成功
3读取中
写入的内容9
9读取成功
写入的内容3
3读取成功

可见: 读时多个线程同时 写入时仅能有一个 读-读-可同时执行 读-写-不可同时执行 写-写-不可同时执行

读锁=共享锁 独占锁=写锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的JUC(java.util.concurrent)包提供了一些并发编程中常用的类,这些类可以帮助我们更方便地实现多线程编程。以下是一些常用JUC类及其解析: 1. CountDownLatch(倒计时器) CountDownLatch是一个计数器,它允许一个或多个线程等待一组事件发生后再继续执行。它最基本的方法是await()和countDown()。await()方法会阻塞当前线程,直到计数器的值为0;countDown()方法会将计数器的值减1。 2. CyclicBarrier(循环屏障) CyclicBarrier是一个同步工具,它允许一组线程等待彼此达到一个公共屏障点。当所有线程都到达这个屏障点时,它们才能继续执行。CyclicBarrier可以被重复使用,当所有线程都执行完后,它会自动重置。 3. Semaphore(信号量) Semaphore是一种计数器,它维护了一组许可证。当调用acquire()方法时,线程会阻塞,直到许可证可用;而当调用release()方法时,许可证的数量会增加。Semaphore可以用于限制同时访问某些资源的线程数量。 4. ReentrantLock(重入) ReentrantLock是一个可重入的互斥。它和synchronized关键字类似,但是提供了更多的灵活性和功能。ReentrantLock中最常用的方法是lock()和unlock(),它们分别用于获取和释放。 5. ConcurrentHashMap(并发哈希表) ConcurrentHashMap是一个线程安全的哈希表实现。它和HashMap类似,但是支持并发访问。ConcurrentHashMap中的所有方法都是线程安全的,而且它的性能比Hashtable和同步的HashMap要好。 6. Executors(线程池) Executors是一个工厂类,用于创建各种类型的线程池。它提供了一些静态方法,例如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等,可以方便地创建各种类型的线程池。 7. Future(异步计算) Future是一个接口,它表示一个异步计算的结果。Future可以通过get()方法获取计算结果,或者通过cancel()方法取消计算。Future还可以用于实现一些高级的并发操作,例如等待一组异步计算全部完成后再继续执行。 总的来说,JUC包提供了很多有用的类和工具,可以帮助我们更方便地实现多线程编程,提高程序的并发性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值