`

JAVA 模拟瞬间高并发

阅读更多
前些日子接到了一个面试电话,面试内容我印象很深,如何模拟一个并发?当时我的回答虽然也可以算是正确的,但自己感觉缺乏实际可以操作的细节,只有一个大概的描述。

      当时我的回答是:“线程全部在同一节点wait,然后在某个节点notifyAll。”

      面试官:“那你听说过惊群效应吗?”

      我:“我没有听过这个名词,但我知道瞬间唤醒所有的线程,会让CPU负载瞬间加大。”

      面试官:“那你有什么改进的方式吗?”

      我:“采用阻塞技术,在某个节点将所有的线程阻塞,在利用条件,线程的个数达到一定数量的时候,打开阻塞。”

      面试官好像是比较满意,结束了这个话题。

      面试结束后,我回头这个块进行了思考,要如何进行阻塞呢?我首先有一个思路就是,利用AtoInteger计算线程数,再利用synchronize方法块阻塞一个线程,根据AtoInteger的判断,执行sleep。

      代码如下:

 

/**
* Created with IntelliJ IDEA.
* User: 菜鸟大明
* Date: 14-10-21
* Time: 下午4:34
* To change this template use File | Settings | File Templates.
*/
public class CountDownLatchTest1 implements Runnable{
final AtomicInteger number = new AtomicInteger();
volatile boolean bol = false;

@Override
public void run() {
System.out.println(number.getAndIncrement());
synchronized (this) {
try {
if (!bol) {
System.out.println(bol);
bol = true;
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("并发数量为" + number.intValue());
}

}

public static void main(String[] args) {
ExecutorService pool = Executors. newCachedThreadPool();
CountDownLatchTest1 test = new CountDownLatchTest1();
for (int i=0;i<10;i++) {
pool.execute(test);
}
}
}

 

  结果为:

 

0
2
1
4
3
false
5
6
7
8
9
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10
并发数量为10

 

从结果上来看,应该是可以解决问题,利用了同步锁,volatile解决了同时释放的问题,难点就在于开关。

后来查找资料,找到了一个CountDownLatch的类,专门干这个的

CountDownLatch是一个同步辅助类,犹如倒计时计数器,创建对象时通过构造方法设置初始值,调用CountDownLatch对象的await()方法则处于等待状态,调用countDown()方法就将计数器减1,当计数到达0时,则所有等待者或单个等待者开始执行。

 

构造方法参数指定了计数的次数

 

new CountDownLatch(1)

 

countDown方法,当前线程调用此方法,则计数减一
new CountDownLatch(1)

 

awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
cdOrder.await();  

  

a直接贴代码,转载的代码
/**
 *
 * @author Administrator
 *该程序用来模拟发送命令与执行命令,主线程代表指挥官,新建3个线程代表战士,战士一直等待着指挥官下达命令,
 *若指挥官没有下达命令,则战士们都必须等待。一旦命令下达,战士们都去执行自己的任务,指挥官处于等待状态,战士们任务执行完毕则报告给
 *指挥官,指挥官则结束等待。
 */
public class CountdownLatchTest {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool(); //创建一个线程池
        final CountDownLatch cdOrder = new CountDownLatch(1);//指挥官的命令,设置为1,指挥官一下达命令,则cutDown,变为0,战士们执行任务
        final CountDownLatch cdAnswer = new CountDownLatch(3);//因为有三个战士,所以初始值为3,每一个战士执行任务完毕则cutDown一次,当三个都执行完毕,变为0,则指挥官停止等待。
        for(int i=0;i<3;i++){
            Runnable runnable = new Runnable(){
                public void run(){
                    try {
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "正准备接受命令");
                        cdOrder.await(); //战士们都处于等待命令状态
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "已接受命令");
                        Thread.sleep((long)(Math.random()*10000));
                        System.out.println("线程" + Thread.currentThread().getName() +
                                "回应命令处理结果");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        cdAnswer.countDown(); //任务执行完毕,返回给指挥官,cdAnswer减1。
                    }
                }
            };
            service.execute(runnable);//为线程池添加任务
        }
        try {
            Thread.sleep((long)(Math.random()*10000));
            System.out.println("线程" + Thread.currentThread().getName() +
                    "即将发布命令");
            cdOrder.countDown(); //发送命令,cdOrder减1,处于等待的战士们停止等待转去执行任务。
            System.out.println("线程" + Thread.currentThread().getName() +
                    "已发送命令,正在等待结果");
            cdAnswer.await(); //命令发送后指挥官处于等待状态,一旦cdAnswer为0时停止等待继续往下执行
            System.out.println("线程" + Thread.currentThread().getName() +
                    "已收到所有响应结果");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        service.shutdown(); //任务结束,停止线程池的所有线程
    }
}

  执行结果:

 

线程pool-1-thread-2正准备接受命令
线程pool-1-thread-3正准备接受命令
线程pool-1-thread-1正准备接受命令
线程main即将发布命令
线程pool-1-thread-2已接受命令
线程pool-1-thread-3已接受命令
线程pool-1-thread-1已接受命令
线程main已发送命令,正在等待结果
线程pool-1-thread-2回应命令处理结果
线程pool-1-thread-1回应命令处理结果
线程pool-1-thread-3回应命令处理结果
线程main已收到所有响应结果

 

上述也是一种实现方式,用countDownLatch的await()方法,代替了synchronize 和 sleep的阻塞功能,通过countDown的方法来当做开关,和计算线程数量的一种方式。

区别的话,肯定是后者会好一些,因为第一种方式依靠sleep(xxx)来阻塞把握不好最短时间,太短了,可能来没有达到固定线程数就会打开开关。

至于两者性能上的区别,目前我还不得而知,有机会测试一下。

 

分享到:
评论

相关推荐

    高并发秒杀案例

    在构建高并发秒杀系统的过程中,我们面临的主要挑战是如何在短时间内处理大量的用户请求,确保系统的稳定性和用户体验。这里,我们将围绕“高并发秒杀案例”这一主题,结合使用SpringMVC和Mybatis两大技术框架,深入...

    SSM实战项目——Java高并发秒杀API.zip

    SSM实战项目——Java高并发秒杀API是一个典型的Java Web开发案例,主要涉及Spring、SpringMVC和MyBatis这三大框架的整合应用。在这个项目中,开发者将学习如何构建一个能够处理高并发请求的秒杀系统,以满足电商或...

    高并发秒杀系统

    为了确保系统的稳定性和性能,我们需要进行压力测试、性能测试,模拟高并发场景下的系统行为。同时,通过监控系统资源(CPU、内存、网络)、日志分析等手段,及时发现并解决问题。 总结,这个项目展示了如何运用SSM...

    java秒杀实战.zip

    JMeter是一款强大的性能测试工具,我们可以通过它模拟高并发场景,对秒杀系统进行压力测试,检查系统的性能瓶颈,优化系统架构。测试指标包括响应时间、吞吐量、并发用户数等,帮助我们评估系统的承载能力。 五、...

    ssm高并发之秒杀系统.rar

    10. **测试与监控**:进行压力测试,模拟高并发场景,检查系统的稳定性和性能。同时,利用监控工具(如Prometheus、Grafana)实时监控系统指标,以便在问题发生时快速定位和解决。 综上所述,"ssm高并发之秒杀系统...

    java时钟java。java

    2. **创建时钟对象**:在`java.time`包中,`Clock`类是用于获取当前瞬间的抽象。你可以使用`Clock.systemDefaultZone()`或`Clock.systemUTC()`来获取默认时区或UTC时钟。`Clock`类还可以用于获取精确的系统时间,这...

    模拟双11、618活动商品秒杀,瞬间大流量并发、引入消息中间件rabbitmq、缓存Nosql、-miaosha.zip

    为了应对这种高并发场景,通常会采用一系列技术手段来保证系统的稳定性和效率。本项目"模拟双11、618活动商品秒杀"便是针对此类问题进行的技术实践,通过引入消息中间件RabbitMQ和NoSQL缓存来优化处理流程。 首先,...

    【源码版】基于SpringMVC的电商高并发秒杀系统设计思路

    在构建一个基于SpringMVC的电商高并发秒杀系统时,设计思路往往涉及到多个关键领域。首先,我们从系统架构层面来分析,秒杀场景下的系统设计需要考虑到以下几个核心要点: 1. **高并发处理**:秒杀活动通常会引来...

    JAVA程序GOHOME自动抢票

    在自动抢票程序中,Java可以提供稳定的运行环境和高效的处理能力,确保程序在高并发环境下依然能够快速响应。 其次,自动抢票的核心是模拟用户操作,这涉及到网络请求和网页解析。Java的HttpURLConnection或者...

    基于redis的秒杀系统模拟

    6. **限流与熔断**:为了避免瞬间高并发导致系统崩溃,可以引入限流策略,如漏桶算法或令牌桶算法,限制进入系统的请求速率。同时,结合熔断机制,当系统压力过大时,快速拒绝请求,保护系统不受损害。 7. **缓存...

    Java毕业设计-基于微服务的商城秒杀系统源码.zip

    5. **高并发处理**:秒杀场景的并发量大,需要采用如预生成令牌、队列限流、分布式锁等手段控制流量,防止系统被瞬间大流量击垮。例如,使用Redis实现分布式锁,确保同一时刻只有一个请求能够执行秒杀操作。 6. **...

    miaosha:模拟双11、618活动商品秒杀,瞬间大流量并发、引入消息中间件rabbitmq、缓存Nosql、做静态缓存、使用jmeter做压测

    首先,Java作为后端开发的主流语言,其丰富的库和框架为处理高并发提供了强大的支持。在秒杀系统中,我们需要考虑的关键是减少数据库的直接访问,以防止因大量请求导致的数据库瓶颈。这就需要用到缓存技术。 NosQL...

    Java互联网秒杀系统的设计与实现,含数据库文件

    秒杀系统是互联网行业中一种常见的高并发场景,用于在短时间内处理大量用户请求,例如限时抢购、热门商品的瞬间售卖等。在这个系统的设计与实现中,Java作为后端开发的主要语言,发挥了其强大的多线程处理能力和丰富...

    秒杀项目-非常值得

    秒杀活动的瞬间流量往往非常大,因此系统必须能够承受高并发访问。这涉及到服务器集群、负载均衡、分布式缓存等技术的应用。例如,使用Nginx作为反向代理和负载均衡器,将请求分发到多个后端服务器,确保单点压力...

    java工具类

    - `java.nio.file.Files`: NIO.2引入的类,提供了更高级别的文件操作,如读写文件、检查权限、计算哈希值等。 3. **日期时间工具类**: - `java.util.Date`: 代表一个具体的瞬间,可以精确到毫秒。 - `java.text...

    基于Java的B2C网上拍卖秒杀与竞价系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频).zip

    项目可能使用了Java的并发库,如synchronized关键字、ReentrantLock等,以及Spring的异步处理机制,来保证在高并发下的数据一致性。 6. **缓存技术**:为了提高性能,系统可能会使用Redis或Memcached等内存数据库...

    redis分布式锁实现抢单秒杀

    在IT行业中,尤其是在高并发的电子商务系统中,"redis分布式锁实现抢单秒杀"是一个常见的挑战。这个场景模拟了多个用户同时参与秒杀活动,系统需要确保库存的准确性和抢单的公平性,避免超卖和数据不一致的问题。...

    springboot-seckill

    在测试阶段,我们可以使用Spring Boot的MockMVC进行单元测试和集成测试,模拟高并发场景,确保系统在实际运行中的稳定性。此外,SpringBoot还支持Actuator组件,用于监控系统的健康状态和性能指标。 总的来说,...

    淘宝红绿仙女版--自己搭建

    需要进行单元测试、集成测试和压力测试,模拟真实环境下的抢购场景,确保系统在高并发情况下仍能正常运行。 总结来说,淘宝红绿仙女版的搭建涉及前端开发、后端开发、数据库设计、服务器配置、负载均衡、高并发处理...

Global site tag (gtag.js) - Google Analytics