2 并发编程初体验

2018-09-24  本文已影响0人  十丈_红尘
1️⃣前言

在开始真正的讲解以前,我们实现一个简单的场景-实现一个计数功能

计数功能 : CountExample

@Slf4j
public class CountExample {
    // 请求总数
    public static int clientTotal = 5000;
    // 同时并发执行的线程数
    public static int threadTotal = 200;
    public static int count = 0;

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        for (int index = 0; index < clientTotal ; index++) {
            exec.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        exec.shutdown();
        log.info("count:{}", count);
    }

    private static void add() {
        count++;
    }
}

计数功能 : MapExample

@Slf4j
public class MapExample {
    private static Map<Integer, Integer> map = Maps.newHashMap();
    // 请求总数
    public static int clientNum = 5000;
    // 同时并发执行的线程数
    public static int threadNum = 200;

    public static void main(String[] args) throws Exception {
        ExecutorService exec = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadNum);
        for (int index = 0; index < clientNum ; index++) {
            final int threadNum = index;
            exec.execute(() -> {
                try {
                    semaphore.acquire();
                    func(threadNum);
                    semaphore.release();
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        exec.shutdown();
        log.info("size:{}", map.size());
    }

    private static void func(int threadNum) {
        map.put(threadNum, threadNum);
    }
}
从上面两个demo的运行结果可以看出,并发情况下每一次的运行结果都是小于5000的,且每次都有可能会不一样(大家可以多尝试几次就会发现,值一直会小于5000且可能每次值都不一样),那么我们如果把两个demo同时允许的进程数修改为1又会是什么样的呢?
CountExample运行结果 MapExample运行结果

从以上实例中我们可以看到,当我们在多线程并发的情况下执行一个简单的累加操作,出错的概率非常的高,这个时候我们就需要思考一下并发环境下到底应该如何编码?到底有哪些手段可以保证并发下的结果是正确的?


2️⃣并发与高并发的基本概念
并发

同时拥有两个或者多个线程,如果程序在单核处理上运行,多个线程将交替地换入或者换出内存,这些线程是同时"存在"的,每个线程都处于执行过程中的某个状态,如果运行在多核处理器上,此时,程序中的每个线程都将分配到一个处理器核上,因此可以同时运行;


高并发

高并发(High Concurreny)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求;


基本概念

单纯的说概念可能有点难以理解,我们来简单对比一下并发与高并发;当我们说多线程并发时我们谈论的是什么呢?其实更多的是讨论多个线程操作相同的资源,这个时候我们谈论的点多数情况下是落实在保证线程安全,合理分配或者使用资源上边;那么当我们谈论高并发时我们谈论的又是什么呢?高并发主要是指系统运行过程中短时间内要大量操作请求的情况,它主要发生在系统集中收到了大量的请求比如12306以及天猫的双十一;这种情况的发生会导致系统在这段时间内会执行大量的操作,例如对资源的请求对数据库的操作等等,如果高并发处理不好不仅仅会降低用户的体验度(请求时间变长)同时也有可能会导致系统宕机,严重的甚至会导致OOM异常 系统停止工作等情况;如果想要系统适应高并发的状态,就要从多个方面对系统进行优化,包括硬件 网络 系统架构以及开发语言的选取 数据结构的运用 算法的优化 数据库优化等等;这个时候我们谈论的更多的是如何提高现有程序的性能,更多的是对高并发场景提高一些解决方案 思路 手段;

上一篇下一篇

猜你喜欢

热点阅读