ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

《并发与高并发系列第一集-基础与概念》

2021-06-13 21:02:05  阅读:174  来源: 互联网

标签:面试官 系列 mainLock 第一集 并行 并发 线程 安琪拉


面试官:看你简历上写,最近正在写并发编程方面的博客,是吧?

安琪拉:闲来无事,看看闲书,写写段子,承蒙读者厚爱,有此打算。

面试官:少跟我这拽文,“闲来无事”?阿里不用996吗?

安琪拉:修福报,你知道吗?… 技术人的日常,能算996吗?

面试官:算了算了,还是聊正题,你先跟我讲讲什么是并发?

安琪拉:并发就是存在两个或多个线程,这些线程同时操作相同的物理机中的资源。

面试官:那并发跟并行有什么区别呢?

安琪拉:举个生活中的例子就懂了:

  • 你在打王者荣耀,这个时候女朋友找你视频,你一直打完王者荣耀才接,说明你不支持并发(也不支持并行);

  • 你在打王者荣耀,这个时候女朋友给你发了微信,你退出王者荣耀,回完微信再回到王者,微信和王者间来回切换,说明你支持并发,但不支持并行;

  • 你在打王者荣耀,这个时候女朋友给你打电话,你边打荣耀边接电话,说明你支持并行。

并行的关键点是物理的“同时”,我们在单核CPU的时候,既能写代码也能听歌,这个多线程实际是基于操作系统根据CPU时间片做的任务轮转,是伪“同时”,只能说是并发,不能算并行,但是多核CPU可以支持每个核同时运行任务,是真实的“同时”,是并行。

Erlang 之父 Joe Armstrong 画了一张图解释了并发与并行的区别,Concurrent (并发),Parallel (并行)。

图片

并发允许二队小孩轮流使用咖啡机,并行是同时存在二台咖啡机,二队小孩同时使用,不冲突。

面试官:那高并发呢?你了解高并发吗?

安琪拉:【心里想,该来的还是来了,要造火箭了】

你说High Concurrency(高并发)是吧(先拽句英文)。

通常我们谈论并发的时候,更多的关注点在于线程安全,但是讨论高并发时,关注点不仅仅是线程安全问题,而是如何在短时间内处理大量请求,保证系统响应时间和吞吐量的可靠,更多关注的是稳定性问题(SRE),高并发涉及的是完整的系统知识,线程安全只是其中一小部分。

高并发是现在互联网设计系统中需要考虑的一个重要因素之一,通常来说,就是通过严谨的设计来保证系统能够同时并行处理很多的请求。这就是大家常说的「 高并发 」。也就是说系统能够在某一时间段内提供很多请求,但是不会影响系统的性能。如果想设计出高可用和高性能的系统,就应该从很多的方面来考虑,例如应该从硬件、软件、编程语言的选择、网络方面的考虑、系统的整体架构、数据结构、算法的优化、数据库的优化等等多方面。这其中的每一点展开来说都要说很多的知识,安琪拉会在后续课程更新这部分内容。

面试官:那你跟我讲讲你们系统的QPS有多少?

安琪拉:大促场景能有个10W+的QPS,日常业务高峰期也有2W+,其他时间几千。

其实对于大部分的系统,几十、几百很正常,QPS能过千的就已经不低了,有的业务会有峰值,QPS稳定过万的系统实际中不多,所以大家日常可以关注一下自己系统的QPS,这个问题面试经常会问。

面试官:一般我们有什么工具可以模拟并发请求呢?

安琪拉:PostMan、Apache Bench(AB)、Jmeter,推荐使用Jmeter。

面试官:那你能写段代码,演示一下并发安全的问题吗?

安琪拉:可以啊。笔递给我一下,顺便帮我拿下A4纸。

public class ConcurrencySafeTest {

    private static int counter = 0;

    public static void main(String[] args) {
        //使用线程池
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        //提交2000个任务
        for(int i = 0; i < 2000; i++) {
            threadPool.submit(new Add());
        }
        threadPool.shutdown();
        System.out.println(counter);
    }

    static class Add implements Runnable {
        @Override
        public void run() {
            counter++;
        }
    }
}

我们进行计数操作,执行2000次,预期的执行结果应该是2000,但是实际执行结果如下:

1971
1987

因为《并发》系列是从基础开始讲的,上面的代码部分内容涉及到后面的一些内容,比如线程池和线程的使用,这里只要大致了解并发的安全问题,后面会有详细说明,后面面试官的问题作为扩展阅读。

面试官:看到你代码中用了CachedThreadPool,那2000次任务执行,CachedThreadPool 线程池创建了多少个线程?

安琪拉:答案是不确定,CachedThreadPool 缓存了线程(复用线程),没有让任务排队,来一个任务,要么复用已有线程处理,要么新建一个线程处理。那我们怎么确定线程池创建过多少个线程呢?可以加一段代码打印出来。

如下:

private static int counter = 0;

public static void main(String[] args) {
//使用线程池
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
//提交2000个任务
for(int i = 0; i < 2000; i++) {
threadPool.submit(new Add());
}
threadPool.shutdown();
//打印最多使用线程数
System.out.println("largestPoolSize:" + threadPool.getLargestPoolSize());
System.out.println(counter);
}

输出结果如下:

第一次:
largestPoolSize:11
1937
第一次:
largestPoolSize:14
1956
第一次:
largestPoolSize:31
1970

可以看到每次都不一样,线程池之前有文章讲过,这个系列后面还会深入讲解。

关于 largestPoolSize, 注释说明了,记录线程池中最大的线程数。

/**
* Tracks largest attained pool size. Accessed only under
* mainLock.
*/
private int largestPoolSize;

面试官:看你代码中写了调用线程池的shutdown,那shutdown 和 shutdownNow 方法什么区别?

安琪拉:shutdown 是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。而shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。

源码对比:

//shutdown
public void shutdown() {
  final ReentrantLock mainLock = this.mainLock;
  mainLock.lock();
  try {
    checkShutdownAccess();
    //设置线程池状态为SHUTDOWN
    advanceRunState(SHUTDOWN);
    interruptIdleWorkers();
    onShutdown(); // hook for ScheduledThreadPoolExecutor
  } finally {
    mainLock.unlock();
  }
  tryTerminate();
}

public List<Runnable> shutdownNow() {
  List<Runnable> tasks;
  final ReentrantLock mainLock = this.mainLock;
  mainLock.lock();
  try {
    checkShutdownAccess();
    //设置线程池状态为STOP
    advanceRunState(STOP);
    interruptWorkers();
    //把队列剩余等待执行任务取出,返回
    tasks = drainQueue();
  } finally {
    mainLock.unlock();
  }
  tryTerminate();
  return tasks;
}

面试官:线程池有哪几种状态?

安琪拉:5种,注意这里说的是线程池的状态,不是线程的状态。下面是线程池的状态流转图:

图片

本文是《并发》系列第一集,主要介绍了一些并发、并行、高并发的一些基础概念,以及并发安全问题的案例,下一集讲并发的风险与优势和CPU多级缓存,以及一些内存操作的指令,然后说Java内存模型。

完整大纲参考:

图片

标签:面试官,系列,mainLock,第一集,并行,并发,线程,安琪拉
来源: https://blog.csdn.net/zhengwangzw/article/details/117885363

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有