2020-

只有光头才能变强。

文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y

在上周总结了一篇「工作中常用到的Java集合类」,反响还不错。这周来写写Java另一个重要的知识点:「多线程

多线程大家在初学的时候,对这个知识点应该有不少的疑惑的。我认为主要原因有两个:

  • 多线程在初学的时候不太好学,并且一般写项目的时候也很少用得上(至少在初学阶段时写的项目基本不需要自己创建线程)。
  • 多线程的知识点在面试经常考,多线程所涉及的知识点非常多,难度也不低。

这就会给人带来一种感觉「这破玩意涉及的东西是真的广,平时也不怎么用,怎么面试就偏偏爱问这个鬼东西

不多BB,我要开始了。

为什么使用多线程?

首先,我们要明确的是「为什么要使用多线程」,可能有人会认为「使用多线程就是为了加快程序运行的速度啊」。如果你是这样回答了,那面试官可能会问你「那多线程是怎么加快程序运行速度的?」

于我的理解:使用多线程最主要的原因是提高系统的资源利用率

现在CPU基本都是多核的,如果你只用单线程,那就是只用到了一个核心,其他的核心就相当于空闲在那里了。

厕所的坑位有5个,如果只用一个坑位,那不是很亏?比如现在我有5个人要上厕所。

在单线程的时候:进去一个人解决要10分钟,然后后面的人都得等一个坑位。那总的时间就要花费50分钟。

在多线程的时候,进去一个人要解决10分钟,然后后面的人发现还有别的坑位,就去别的坑位了,不是傻瓜地等一个坑位。

我们可以把「等坑位」看作是IO操作,众所周知IO操作相对于CPU而言是非常慢的,CPU等待IO那段时间是空闲的。如果我们需要做类似IO这种慢的操作,可以开多个线程出来,尽量不要让CPU空闲下来,提高系统的资源利用率。

说白了,我们就是在**「压榨」**CPU的资源。本来就有的资源,如果有需要,我们就应当好好利用。

多线程不是银弹,并不是说线程越多,我们的资源利用效率就越好。执行IO操作我们线程可以适当多一点,因为很多时候CPU是相对空闲的。如果是计算型的操作,本来CPU就不空闲了,还开很多的线程就不对了(有多线程就会有线程切换的问题,线程切换都是需要耗费资源的)

多线程离我们远吗?

多线程其实离我们很近,只是很多时候我们感知不到它的存在而已。

Tomcat我相信每个Java后端的同学都认识它,它就是以多线程去响应请求的,我们可以在server.xml中配置连接池的配置,比如:

<Connector port="8080" maxThreads="350" maxHttpHeaderSize="8192" minSpareThreads="45" maxPostSize="512000" protocol="HTTP/1.1" enableLookups="false" redirectPort="8443" acceptCount="200" keepAliveTimeout="15000" maxKeepAliveRequests="-1" maxConnections="25000" connectionTimeout="15000" disableUploadTimeout="false" useBodyEncodingForURI="true" URIEncoding="UTF-8" />

 
   
   
   
   
  • 1

Tomcat处理每一个请求都会从线程连接池里边用一个线程去处理,这显然是多线程的操作。然后这个请求线程顺藤摸瓜到了我们的Servlet,执行对应的service()方法。

而我们的service方法是无状态的,多个线程请求service方法,往往都没有操作共享变量,不操作共享变量就不会有线程安全问题。

上面只是用了Servlet举例,我们常用的SpringMVC其实也是一样的(毕竟底层还是Servlet)。

还有我们在连接数据库的时候,也会用对应的连接池(Druid、C3P0、DBCP等),比如常见的Druid配置:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
     <property name="url" value="${jdbc_url}" />
     <property name="username" value="${jdbc_user}" />
     <property name="password" value="${jdbc_password}" />
 <property name="filters" value="stat" />

 <property name="maxActive" value="20" />
 <property name="initialSize" value="1" />
 <property name="maxWait" value="60000" />
 <property name="minIdle" value="1" />

 <property name="timeBetweenEvictionRunsMillis" value="60000" />
 <property name="minEvictableIdleTimeMillis" value="300000" />

 <property name="testWhileIdle" value="true" />
 <property name="testOnBorrow" value="false" />
 <property name="testOnReturn" value="false" />

 <property name="poolPreparedStatements" value="true" />
 <property name="maxOpenPreparedStatements" value="20" />

 <property name="asyncInit" value="true" />

bean>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

我想说的是:我们日常开发的程序几乎都是多线程模式的,只是绝大多数时候我们没感知到而已。很多时候都是框架帮我们屏蔽掉了。

多线程知识重要吗?

从上面总结下来,我们可以发现:我们日常「关于多线程的代码」写得不多,但是我们写的程序代码的的确确是在多线程的环境下跑的。

如果我们不懂多线程知识,很直接的一个现实:

生成结果

从文章最开头的思维导图,我们可以发现多线程的知识点还是很多的,我们起码得知道:

  • 线程和进程的区别
  • Thead类的常见方法
  • 可以用什么手段来解决线程安全性问题
  • Synchronized和Lock锁的区别
  • 什么是AQS、ReentrantLock和ReentrantReadWriteLock锁
  • JDK自带的线程池有哪几个,线程池的构造方法重要的参数
  • 什么是死锁,怎么避免死锁
  • CountDownLatch、CyclicBarrier、Semaphore是什么?
  • Atomic包下的常见子类,什么是CAS,CAS会有什么问题
  • ThreadLocal是什么?
  • …//

虽然在工作中未必会全部用得上,但如果项目真的用到了,我们如果学过了可能就可以很快地理解当时为什么要这样设计(我觉得去挖掘过程还是挺有意思的)。

我可能不用,但你必须要有

这个道理也很容易懂:「我买电脑的时候,虽然我是木耳听不出什么音质出来,但你音质就是得好」。企业招人的时候也一样「你在工作的时候未必要写,但你必须要会

至少在我看来,从求职的角度触发,多线程是很重要的。之前我还整理过在我当时校招经常被问到的多线程面试题目:

  1. 多线程了解多少啊?使用多线程会有什么问题?你是怎么理解“线程安全”的?
  2. 如果我现在想要某个操作等待线程结束之后才执行,有什么方法可以实现?为什么要用CountDownLatch?CountDownLatch的底层是什么?(引出AQS)
  3. synchronized关键字来说一下,它的用途是什么?synchronized底层的原理是什么?
  4. 线程安全的容器有哪些?(着重于ConcurrentHashMap、CopyWriteOnArrayList与其他非线程安全容器的区别以及它们的具体实现)
  5. ThreadLocal你了解过吗?主要是用来干什么的?具体的源码实现原理来说一下吧
  6. 产生死锁的条件是什么?我们可以如何避免死锁?(可延伸到操作系统层面上的死锁)
  7. synchronized锁和ReentrantLock锁有什么区别呀?
  8. 线程池你应该也看过吧,来说说为什么要用线程池。JDK默认实现了几个线程池,分别有xxx(自然地ThreadPoolExecutor构造函数的常用几个参数你也得一起说出来)

我在工作中用到的线程知识有哪些

本来是打算这篇文章主旋律就写这块的,然后我翻了一下自己维护的系统,用到的线程的地方还真的不是很多…

我就拿我现在的系统用到线程相关知识的几个例子吧。

线程池

我这边有个调度系统,运营设置了对应的时间,该任务就去执行,执行的内容大致就是去读HDFS文件,然后将数据组装,再传递到下游。

任务触发了以后,我们直接将这个任务交给一个线程池去处理,交由线程池后就直接返回SUCCESS

这样做的好处是什么?如果多个任务同时触发,那可能某些任务执行时间过长,请求可能会被阻塞住,而我们如果放在线程池中可以提高系统的吞吐量。

使用线程池的时候,往往我们的调用方都不需要考虑请求是否立马处理成功。假设线程池在处理任务的时候因为某些原因失败了,我们可以走报警机制(用邮件/短信等渠道去提醒请求方即可)。

不知道大家学过消息队列了没有,我们常常说消息队列是异步的,很多时候调用方的请求我们丢到消息队列里边,就告诉调用方我们这条请求处理成功了。实际上,这个请求可能还交由下游的多个系统去处理,下游的系统可能也是异步的…

在使用线程池的时候,很多时候我们也是把他当做异步来使(WebFlux实际上也是将请求丢到线程池嘛),只要我们的系统之间交互不是强一致性的,又希望提高系统的吞吐量,我们就可以考虑使用线程池。

轮询

有的时候,我们需要有一个线程去轮询处理某些任务。

比如,我的系统会有发短信的功能,我调用渠道商的下发接口的后,我需要拿到短信的回执信息,于是我就需要去调用渠道商的回执接口。

此时最简单的做法就是开一个线程,不断的轮询渠道商的回执接口(我们设定轮询的间隔时间即可)

Thread thread = new Thread(new Runnable() {
  @Override
  public void run() {
    while (true) {
      try {
        // 间隔一段时间轮询一次                                           
        TimeUnit.MILLISECONDS.sleep(period);
    // 调用接口
    String result = http.post();

    // 得到result后进行处理(比如将结果插入到数据库)
    smsDao.insert(result);
  }
}

});
thread.start();

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

或者有的时候,我们把任务放到内存阻塞队列或者Redis,也是通过一个线程轮询去取「队列」的数据。

借助juc包实现线程安全

juc其实就是java.util.concurrent

我们在使用线程的时候,或者在日常开发的时候,都是得考虑我们现在使用的场景是否是线程安全的。

如果不是线程安全的,我们可以做什么东西来使我们的程序变得线程安全。

  • 如果是集合,我们可以考虑一下juc包下的集合类。
  • 如果是数值/对象,我们可以考虑一下atomic包下的类。
  • 如果是涉及到线程的重复利用,我们可以考虑一下是否要用线程池。
  • 如果涉及到对线程的控制(比如一次能使用多少个线程,当前线程触发的条件是否依赖其他线程的结果),我们可以考虑CountDownLatch/Semaphore等等
  • 如果synchronized无法满足你,我们可以考虑lock包下的类


img

涵盖Java后端所有知识点的开源项目(已有6 K star):https://github.com/ZhongFuCheng3y/3y

如果大家想要实时关注我更新的文章以及分享的干货的话,微信搜索Java3y

PDF文档的内容均为手打,有任何的不懂都可以直接来问我(公众号有我的联系方式)。

为了学好Java,我尝试了这 6 个方法,没想到这个对我帮助最大...
11-18
这里有一套关于java的学习方法,内含项目实战+面试技巧+就业规划
Java开发5年,四面美团(多线程+redis+JVM+数据库),终拿offer
程序员追风的博客
04-03 5685
面试题来源自网络……

前言

Java开发五年多.投递阿里、腾讯、头条、美团、京东等各互联网公司的高级Java岗位,最终得到了美团的面试机会,并成功拿下美团高级Java岗的offer。美团Java岗四面,前三面都是技术面,第四面是HR面,下面是面试题!

美团Java岗一面(技术,电话面,约40分钟)

自我介绍。


项目介绍。


了解过redis源码及redis集群么?...
  • love_aya
    love_aya:还真找了一个能做多人运动,五人开黑的厕所的照片出来o_o7月前回复举报
    41
  • weixin_43508427
    垲先生:所以,大佬讲了这么多干货,你们就只看到了多人运动五黑厕所?表情包表情包7月前回复举报
    18
  • <
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • >
卧槽,多线程都不会?后浪你好意思吗!
JAVA葵花宝典
05-19 216
小A你好 面试官,非常高兴能参加今天的面试 面试官没事,先做一个自我介绍吧小A我叫小A,工作三年了,做过...... 面试官嗯,好的,看到你的项目这块,在公司主要用的就是spring全家桶相关...
程序员吐槽:面试牛皮吹得太大,被高薪录取后反而不敢去了
程序员职场生活
05-11 1591
我们人生中有时会有那么一种迷茫,突然一下被人家认同有些难以置信,就连自己也开始怀疑自己,产生“自己真的有这么厉害吗?被人高估怕让人家失望”的想法,就有那么一个程序员就是如此。他在一家公司面试得到的评价很高,高的让自己都产生了怀疑,害怕自己入职后达不到他们当初的期望,不知道该去还是不去?

对于这种情况网友们当然认为是要去的啦!有网友表示:薪资高于能力不可怕,入职入职!之后有什么问题加油解决就行,人在办法在。很多人能力出众但高薪一直难求,你这样的情况好太多了!对于这位网友的建议楼主也表示感谢道:好的,谢谢。


看代码猜古诗哈哈逗死我了_紫气伯爵的博客-CSDN博客_c语言猜诗词...
7-9
多线程, 面试官 立马 给我发offer 不小心拿了几个 offer,有点烦 weixin_33830216的博客 1万+ 什么是单点登录(SSO) 前言只有光头才能变强。文本已...
多线程(一)——通过实现Runnable接口创建线程_STICK TO..._CSDN博客
8-25
多线程, 面试官 立马 给我发offer 不小心拿了几个 offer,有点烦 zejian的博客 06-04 25万+ 深入理解Java并发之synchronized实现原理 【版权申明】未...
面试官,不要再问我三次握手和四次挥手
10-09 328
面试官,不要再问我三次握手和四次挥手
十面阿里,七面头条,手拿六个Offer,你猜我最后选了哪家?
技术zhai的博客
05-07 573
面试者背景简介

双非末流一本,大三,软件专业(Java),有百度实习经历

面试情况

十面阿里,总共分为阿里云四面,蚂蚁两面,菜鸟四面;

七面头条分为金融三面,抖音一面,效率工程三面;

六个Offer分别是阿里、腾讯、头条、华为、蘑菇街、三七互娱

从二月份在牛客网看到阿里云的招聘贴就投了,那是我最早投递的公司,当时也没什么经验,导致表现得很糟糕,最后四面跪,当时伤心到谷底,幸好跪得比较早…


4轮面试,5个 面试官,21天斩获京东商城 offer(Java后台开..._CSDN博客
11-13
多线程, 面试官 立马 给我发offer 3y 04-07 8万+ 不小心拿了几个 offer,有点烦 面试题总结 —— JAVA高级工程师 Thancks 03-03 21万+ ...
java面试题学习打卡——第一天_面试_sinat_35803474的博客-CSDN博客
5-14
3y 2万+ 我 多线程, 面试官 立马 给我发offer 不小心拿了几个 offer,有点烦 编码之外的技术博客 5万+ 自从喜欢上了B站这12个UP主,我越来越觉得自己...
同事临走时,给了我这份多线程and高并发(面试题+思维导图),借此我含泪拿下了阿里offer
辻贰的博客
10-22 322
导语:

作为一名Java开发者,听到多线程应该不会感到陌生吧,多线程也是在面试时面试官必问的一个问题了,不多线程还敢自己是做Java开发的吗?

话不多,直接上干货!

一、多线程与高并发(面试题集合总结)

多线程与高并发面试题(基础部分)

你如何确保main()方法所在的线程是Java程序最后结束的线程?
ThreadLocal原理

ThreadLocal内存结构图

什么是死锁(Deadlock)?如何分析和避免死锁?
什么是Java Timer类?如何创建一个有特定…


一文搞定Java并发编程面试考点
weixin_33979745的博客
01-25 2559
2019独角兽企业重金招聘Python工程师标准>>>
     ...
多线程(4)_StarSea-CSDN博客
7-2
多线程(1) 后续知识的学习及扩充 多线程(2) 多线程(3) 好了,我亲爱的读者朋友,以上就是本文的全部内容了!!! 觉得有点用记得给我点赞哦! 通过坚持不懈地学...
leetcode之 Reverse Integer_leetcode,算法,面试_lucky..._CSDN博客
5-14
3y 2万+ 我 多线程, 面试官 立马 给我发offer 不小心拿了几个 offer,有点烦 编码之外的技术博客 5万+ 自从喜欢上了B站这12个UP主,我越来越觉得自己...
面试阿里p7,被按在地上摩擦,鬼知道我经历了什么?
路人甲Java
03-25 14万+
面试阿里p7被问到的问题(当时我只知道第一个):@Conditional是做什么的?@Conditional多个条件是什么逻辑关系?条件判断在什么时候执...
CSDN开发助手,集成开发者常用工具,提升开发效率
支持本地书签、tab页、历史记录搜索; 集成CSDN搜索结果; 他是一个时间转换工具; 他是一个计算器; 他是。。。,更多功能正在添加中
老板黑话大全,成年人一定要看,不要再被骗了!_面试_java..._CSDN博客
5-13
多线程, 面试官 立马 给我发offer 不小心拿了几个 offer,有点烦 编码之外的技术博客 5万+ 自从喜欢上了B站这12个UP主,我越来越觉得自己是个废柴了!
面试官再问ConcurrentHashMap,就将这篇文章甩给他_weix..._CSDN博客
6-30
多线程, 面试官 立马 给我发offer 不小心拿了几个 offer,有点烦 敖丙 1万+ 我把ConcurrentHashMap & HashTable的知识点都整理了一下 都知道Hash...
vue+Echarts动态数据已经赋值,但是无法渲染页面的问题
weixin_43481793的博客
03-13 3万+
vue+Echarts动态数据已经赋值,但是无法渲染页面的问题 最近用vue+Echarts想做一个饼状统计图,但是数据明明已经绑定完毕,但是页面渲染一直没有效果,最终才发现问题所在,自己还是个新手,主要对vue还不是很熟悉。废话不 ,接下来看我的代码: 正常的给个div的大小 <div> <div id="echartss" :style="{width: '100%...
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页

你可能感兴趣的:(2020-)