并发与高并发-并发模拟代码

一、CountDownLatch

1.背景:

  (1)countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。

  (2)存在于java.util.cucurrent包下。

2.概念

  (1)countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。

  (2)是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

3.源码

  (1)countDownLatch类中只提供了一个构造器:

//参数count为计数值
public CountDownLatch(int count) {  };  

  (2)类中有三个方法是最重要的:

//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//将count值减1
public void countDown() { };  

4.示例

普通示例:

public class CountDownLatchTest {

    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(2);
        System.out.println("主线程开始执行…… ……");
        //第一个子线程执行
        ExecutorService es1 = Executors.newSingleThreadExecutor();
        es1.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            }
        });
        es1.shutdown();

        //第二个子线程执行
        ExecutorService es2 = Executors.newSingleThreadExecutor();
        es2.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
                latch.countDown();
            }
        });
        es2.shutdown();
        System.out.println("等待两个线程执行完毕…… ……");
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("两个子线程都执行完毕,继续执行主线程");
    }
}

结果集:

主线程开始执行…… ……
等待两个线程执行完毕…… ……
子线程:pool-1-thread-1执行
子线程:pool-2-thread-1执行
两个子线程都执行完毕,继续执行主线程

模拟并发示例:

public class Parallellimit {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        CountDownLatch cdl = new CountDownLatch(100);
        for (int i = 0; i < 100; i++) {
            CountRunnable runnable = new CountRunnable(cdl);
            pool.execute(runnable);
        }
    }
}

 class CountRunnable implements Runnable {
    private CountDownLatch countDownLatch;
    public CountRunnable(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
        try {
            synchronized (countDownLatch) {
                /*** 每次减少一个容量*/
                countDownLatch.countDown();
                System.out.println("thread counts = " + (countDownLatch.getCount()));
            }
            countDownLatch.await();
            System.out.println("concurrency counts = " + (100 - countDownLatch.getCount()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

*CountDownLatch和CyclicBarrier区别:
1.countDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次
2.CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供reset功能,可以多次使用

参考链接:https://www.jianshu.com/p/e233bb37d2e6

原文地址:https://www.cnblogs.com/jmy520/p/11874872.html

时间: 2024-10-06 04:25:14

并发与高并发-并发模拟代码的相关文章

【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)

声明 特此声明:文中有关支付宝账户的说明,只是用来举例,实际支付宝账户要比文中描述的复杂的多.也与文中描述的完全不同. 前言 很多网友留言说:在编写多线程并发程序时,我明明对共享资源加锁了啊?为什么还是出问题呢?问题到底出在哪里呢?其实,我想说的是:你的加锁姿势正确吗?你真的会使用锁吗?错误的加锁方式不但不能解决并发问题,而且还会带来各种诡异的Bug问题,有时难以复现! 在上一篇<[高并发]如何使用互斥锁解决多线程的原子性问题?这次终于明白了!>一文中,我们知道在并发编程中,不能使用多把锁保护

并发、高并发、集群的含义?

并发:多个用户同时向服务器发出请求,服务器会开启多个线程,每个线程服务一个用户 高并发:当用户量达到成千上万,会导致服务器资源不再充足,最终使服务器内存溢出 集群:可以解决高并发问题  集群将一个应用拷贝多份,搭在多台服务器(机器),多台服务器构成一个集群 原文地址:https://www.cnblogs.com/codeXi/p/11429871.html

Java并发和高并发学习总结(四)- J.U.C之工具类

1.总览 CountDownLatch允许一个或多个线程等待某些操作完成 Semaphore Java版本的信号量实现 CyclicBarrier 一种辅助性的同步结构,允许多个线程等待到达某个屏障 Exchanger 在线程间交换数据的一种手段 2.CountDownLatch 当一个或多个线程需要等待其他线程完成操作时,就可以使用CountDownLatch了,当然,最简单的你也可以使用join方法 2.1.join public class JoinTest { public static

[高并发]Java高并发编程系列开山篇--线程实现

ava是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相同的内存空间进行并发读写操作.这可能是在单线程程序中从来不会遇到的问题.其中的一些错误也未必会在单CPU机器上出现,因为两个线程从来不会得到真正的并行执行.然而,更现代的计算机伴随着多核CPU的出现,也就意味着不同的线程能被不同的CPU核得到真正意义的并行执行. 那么,要开始Java并发之路,就要开始

并发与高并发(十三)J.U.C之AQS

前言 什么是AQS,是AbstractQueuedSynchronizer类的简称.J.U.C大大提高了并发的性能,而AQS又是J.U.S的核心. 主体概要 J.U.C之AQS介绍 J.U.C之AQS-CountDownLatch J.U.C之AQS-Semaphore J.U.C之AQS-CyclicBarrier J.U.C之AQS-ReentrantLock与锁 主体内容 总结 原文地址:https://www.cnblogs.com/jmy520/p/12337891.html

并发与高并发

二.CPU多级缓存 2-1 CPU高级缓存-缓存一致性(MESI协议) 1.为什么需要CPU缓存? 答:CPU的频率太快了,快到主存赶不上,这样在处理器时钟周期内,CPU常常要等待主存,浪费了资源.所以缓存的出现,是为了缓解CPU和内存之间速度不匹配的问题.(结构:cpu->cache->memory) 2.CPU缓存有什么意义? 答: 1)   时间局部性:如果某个数据被访问,那么在不久的将来它有可能被再次访问. 2)空间局部性:如果某个数据被访问,那么与它相邻的数据很快也可能被访问. 3.

并发与高并发(八)-线程安全性-原子性-synchronized

前言 闲暇时刻,谈一下曾经在多线程教程中接触的同步锁synchronized,相当于复习一遍吧. 主要介绍 synchronized:依赖JVM Lock:依赖特殊的CPU指令,代码实现,ReetrantLock 主体内容 一.那么我们主要先讲解一下关于同步锁synchronized的作用范围. 1.修饰代码块:作用范围-大括号括起来的代码,作用于调用这个代码块的对象,如果不同对象调用该代码块就不会同步. 2.修饰方法:作用范围-整个方法,作用于调用这个方法的对象. 3.修饰静态方法:作用范围-

并发与高并发-线程安全性-可见性

前言 乍看可见性,不明白它的意思.联想到线程,意思就是一个线程对主内存的修改及时的被另一个线程观察到,即为可见性. 那么既然有可见性,会不会存在不可见性呢? 答案是肯定的,导致线程不可见的原因是什么呢? 有三个原因: (1)线程交叉执行. (2)重排序结合线程交叉执行. (3)共享变量更新后的值没有在工作内存与主存间及时更新. 主体内容 一.这里的可见性涉及到synchronized,顺便了解一些一下JMM对synchronized的两条规定: 1.线程解锁前,必须把共享变量的最新值刷新到主内存

并发与高并发(十四)J.U.C组件拓展

前言 J.U.C的拓展组件有哪些?分别在什么场景下使用?如何使用? 主体概要 J.U.C-FutureTask J.U.C-ForkJoin J.U.C-ForkJoin 主体内容 一.J.U.C-FutureTask 1.这里要介绍的第一个组件是FutureTask,这个组件是J.U.C里面的,但它不是AQS的子类.这个类对线程结果的处理值得我们去学习.在学习Java多线程的时候,一定接触过Thread,Runnable,一种是直接继承Thread,另一种就是实现Runnable,这两种方式有