精华内容
下载资源
问答
  • 为什么要使用多线程

    2021-01-05 10:39:38
    为什么要使用多线程 作者:ssssdy
    展开全文
  • 为什么要使用多线程技术

    千次阅读 2017-11-18 10:41:45
    为什么要使用多线程技术

    前言

    为什么要使用多线程技术,这本来应该是个基础的问题,是在学习多线程的时候应该搞懂的问题,可我却在学了多线程之后才开始搞懂这个问题。(敲黑板!)这是本末倒置,大家要注意。

    确实,如果连为什么要使用多线程都没搞懂,就别指望能把多线程给学好了。

    为什么要使用多线程技术?

    像我们一开始学习 JAVA 还没学多线程时,所以代码都是在 main 线程中执行,这没问题。但是,假如我们有多个任务,并且其中有耗时的任务。比方说有三个任务,并且执行顺序依次为任务A,任务B,任务C,假设,任务A是一个耗时的 IO 操作(如读取一个文件中的全部信息),那么,在单线程中,当执行到任务A时,由于任务A进行的是 IO 操作,因此线程会挂起并让出 CPU(注意,IO 操作并不会一直占着 CPU),直到DMA(Direct Memory Access)处理器完成任务(这个过程可能会很久,这是操作系统的知识!!操作系统很重要!),再通过中断告诉CPU完成了,该线程才会再次运行,任务A才可以继续往下执行。因为是单线程,所以任务B必须等到任务A执行完才能执行,任务C必须等到任务B执行完才能执行。如果任务B又是一个耗时的操作,那么任务C要等待的时间就会更久了。

    如果使用了多线程,为两个耗时的任务分别开启线程去执行的话,那么由于三个任务是并发执行的,因此,即使任务A和任务B是耗时操作,那也和任务C没关系,因为他们在不同的线程之间了。

    一个生动形象的例子

    举个例子——在汽车客运站的售票厅(有个不太合理的假设,售票员只有一个)。假设某个窗口有100个人在排队,前三个的人分别是老爷爷、老奶奶、以及赶着去签合同的小明。
    假设老爷爷的记性不太好,当售票员问他要定去往哪里的汽车票时,老爷爷说忘不起了,要打个电话问一问儿子,等问到了,再告诉售票员。(着急的小明黑人问号脸????)于是售票员就跑去其他窗口为其他排队的人服务了。这时排在最后的小明,只能干着急!
    等老爷爷打完电话,并且售票员过来时,老爷爷总算订到票并离开了。(老爷爷的操作可以理解为IO操作)这时,老奶奶便上场了。当售票员问老奶奶要定去往哪里的票的时候,老奶奶竟然说还没想好,要再想一想。排在后面的小明一脸茫然,可是他除了等还能怎样。毕竟这里是公共场所,毕竟人家是老奶奶。于是售票员就走去其他窗口服务了。
    小明此时在想,要是能专门开个窗口为这些慢吞吞的老爷爷老奶奶开个窗口给他们服务就好了,这样他们要考虑多久都没关系,因为在他们考虑的时候售票员可以去其他窗口为其他赶时间的乘客服务。(这就是使用多线程的好处)
    等到老奶奶想好了,然后等到售票员来到老奶奶所在的窗口时,老奶奶也订到她的票了。然后就到小明了,还没等小明开口,可是这时售票员又跑去其他窗口服务了。(毕竟其他窗口也有乘客啊,不能只为你一个窗口服务吧)
    最后,售票员总算来到小明所在的窗口了,售票员在服务的时候,小明抱怨说要是能为那些慢吞吞的设立专门的窗口就好了。售票员微笑表示同意并回答:“这是个好建议,我会跟上级反映一下”。(这里向上级反映就相当于告诉设计程序的人,为耗时的操作开启专门的线程,以不至于导致其他操作一直干等。)小明笑着说:“要是为我这种赶时间速度又快的人设立专门的窗口我觉得也是可以的。”售票员却摇了摇头,并有礼貌的回答:“这可不行,因为像你这样办理速度快的人占的是绝大多数,要是为你们都开启专门的窗口,那得开多少个窗口才够啊,且不说面积够不够,就算够,我跑来跑去,也花掉不少时间啊”。(开启线程是要付出代价的,并不是越多线程效率就越高)
    小明不好意思的点了点头,并问售票员姐姐要了微信。后来…(开玩笑)

    这个例子中,售票员就相当于 cpu,线程就相当于窗口,排队的人就相当于各个任务,售票员跑去哪个窗口就相当于哪个线程获得时间分片。然后还得假设售票员在同一个窗口停留的时间很短,以纳秒为单位,这样以秒为单位来看,售票员就相当于同时服务了很多个窗口,这就是并发。

    并发与并行

    并发是指一个很短的时间间隔内,执行了多个任务。
    并行是指在同一个时刻,执行了多个任务。
    并发也称为伪并行,也就是说,并发,就好像同一时刻,可以执行多个任务。那是因为时间间隔足够短让你以为多个任务是在同一时刻发生了。

    谈到并发,默认前提都是单核 CPU。由于只有一个核,所以同一时刻,只能有处理一件事情。又由于多线程的存在以及 CPU 的效率极高,结果就造就了并发——看起来好像同一时刻 CPU 可以处理多件事情。
    而并行,默认前提则是多核多线程。

    最后

    使用多线程就只有好处没有坏处吗?并不是,使用多线程是要付出代价的,如果没有耗时的任务,使用多线程,效率反而更低,因为cpu 在线程间的切换也需要耗费时间。引用知乎上看到的一句话:

    多线程在CPU密集型的作业下的确不能提高性能甚至更浪费时间,但是在IO密集型的作业下则可以提升性能(或者更准确点说叫平均响应时间)。

    由上得出的结论是,正确的使用多线程可以提高程序的运行效率。

    不过,也由于多线程的存在,带来了线程安全的问题,因此我们要去学线程池、锁机制、CAS、线程安全的容器类等知识去解决线程安全问题。


    如有哪里写的不对,请帮忙指出,感谢!

    展开全文
  • 为什么要使用多线程? 这里举个例子: 在用百度云时(只能单线程运行的情况) 在使用百度云时(可以多线程的运行情况) 总结:使用多线程可以提高程序的效率 ...

    为什么要使用多线程?

    这里举个例子:

    在用百度云时(只能单线程运行的情况)

    在使用百度云时(可以多线程的运行情况)

    总结:使用多线程可以提高程序的效率

    展开全文
  • 【多线程高并发】-为什么要使用多线程?创建多少个线程合适呢? 我们为什么要选择多线程?大多数我们选择多线程的原因就是因为快。但 并发场景在所有场景下都是快的吗? 这个快能否度量呢? 使用多线程就是在正确...

    【多线程高并发】-为什么要使用多线程?创建多少个线程合适呢?

    我们为什么要选择多线程?大多数我们选择多线程的原因就是因为快。但

    • 并发场景在所有场景下都是快的吗?
    • 这个快能否度量呢?

    使用多线程就是在正确的场景下通过设置正确的线程来最大化程序的运行速度。在硬件级别就是充分利用CPU和I/O的利用率。

    在具体场景下,通过是以下两个场景:

    • CPU密集型程序;
    • I/O密集型程序;

    一、CPU密集型程序

    一个完整请求,I/O操作可以在很短时间内完成,但是CPU还有很多运算要处理,也就是说CPU计算的比例占很大一部分。

    比如我们要计算1+2+…100亿的总和,很明显,这就是一个CPU密集型程序。

    假如我们在【单核】CPU下,如果我们创建4个线程来分段计算,即:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Po2zyRm-1617943429303)(multi_thread\00/1.png)]

    由于是单核CPU,所有线程都在等待CPU时间片。按照理想情况来看,四个线程执行的时间总和与一个线程独自完成是相等的,实际上我们还忽略了四个线程上下文切换的开销;

    综上,单核CPU处理CPU密集型程序,这种情况并不适合使用多线程。

    此时如果在4核CPU下,同样创建四个线程来分段计算,看看会发生什么?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UgXGIfRf-1617943429308)(multi_thread\00\2.png)]

    每个线程都有CPU来运行,并不会发生等待CPU时间片的情况,也没有线程切换的开销。理论情况来看效率提升了4倍。

    如果是多核CPU处理CPU密集型程序,完全可以最大化利用CPU核心数,应用并发线程来提高效率。

    二、I/O密集型程序

    与CPU密集型程序相对,一个完整请求,CPU运算操作完成之后还有很多I/O操作要做, 也就是说I/O操作占比很大部分。

    在进行I/O操作时,CPU是空闲状态,所以要最大化利用CPU,不能让其是空闲状态,同样在单核CPU的情况下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hfJlEULM-1617943429310)(multi_thread\00\3.png)]

    从上图中可以看出,每个线程都执行了相同长度的CPU耗时和I/O耗时,如果将上面的图多画几个周期,CPU操作耗时固定,将I/O操作耗时变为CPU耗时的3倍。这时候会发现,CPU又有空闲,这是你就可以新建线程4,来继续最大化利用CPU。

    综上:

    线程等待时间所占比例越高,需要越多线程;线程CPU时间所占比较越高,需要越少线程。

    三、那创建多少个线程合适呢?

    首先是场景问题,从上面知道我们有CPU密集型和I/O密集型两个场景,不同的场景需要的线程数也就不一样。

    CPU密集型程序创建多少个线程合适呢?

    对于CPU密集型程序来说,理论上线程数量=CPU核数(逻辑)就可以了,但是实际上,数量一般会设置为CPU核数+1,为什么呢?

    计算机CPU密集型任务的线程恰好在某时因为发生一个页面错误或者因为其它原因而暂停,刚好有一个额外的线程,可以确保在这种情况下CPU周期不会中断工作。

    I/O密集型程序创建多少个线程合适呢?

    一个CPU核心的最佳线程数=(1/CPU利用率)=1+(I/O耗时/CPU耗时)。

    多个CPU核心的最佳线程数=CPU核心数*(1+(I/O耗时/CPU耗时))

    按照上面的公式,假如几乎全是I/O耗时,纯理论上就可以说是2N(N=CPU核数)。

    如果理论都好用,那就用不着实践了,也就更不会有调优的事情出现了。不过在初始阶段,确实可以按照这个理论作为伪标准,毕竟差也不可能差太多,这样调优会更好一些。

    之后具体调优阶段可以利用一些工具SkyWalkingCATzipkin等调优工具来知道具体的I/O耗时和CPU耗时,以及CPU利用率。

    四、线程场景有关问题

    一、小问一

    假设要求一个系统的TPS(Transaction Per Second或者Task Per Second)至少为20,然后假设每一个Transaction由一个线程完成,继续假设平均每个线程处理一个Transaction的时间为4s。

    如何设计线程个数,使得其可以在1s内处理完这20个transaction?

    因:一个线程一个transaction时间为4s,那每秒一个线程只能处理1/4=0.25个TPS。

    所:1秒内要处理20个TPS,理论线程数=20/0.25=80个。

    但没有考虑到CPU数目,一般服务器的CPU核数为16或者32。如果有80个线程,肯定会带来太多不必要的线程上下文切换开销,这就需要调优,来达到最佳balance。

    二、小问二

    计算操作需要5ms,DB操作需要100ms,对于一台8核CPU的服务器,怎么设置线程数呢?

    线程数=8*(1+100/5)=168个。

    那么如果DB的QPS(Query Per Second)上限是1000,那么此时这个线程数又应该设置为多大呢?

    因为:1s=1000ms,当前一个任务5+100=105ms,那么一个线程每秒可以处理的任务数就是1000/105。

    那么168个线程每秒可以处理的任务数就是168*1000/105=1600QPS。

    而因为QPS的上限是1000,所以线程数就要等比减少为168*1000/1600=105个。

    同样,这也没用考虑CPU数目,接下来就是细节调优的阶段了。

    因为一次请求不仅仅包括CPU和I/O操作,具体的调优过程还要考虑内存资源、网络等具体情况。

    五、增加CPU核心一定能解决问题吗?

    即使算出了理论线程数,但实际上CPU核数不够,会带来线程上下文切换的开销。

    那么下一步就需要增加CPU核数,那盲目的增加CPU核数就一定能解决问题吗?

    有一个阿姆达尔定律,它代表了处理器并行计算后效率提升的能力。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F0p0l6Rp-1617943429314)(multi_thread\00\4.png)]

    这个公式告诉我们,假如我们的串行率是5%,那么无论采用什么技术,最高也就只能提高20倍的性能。

    临界区都是串行的,非临界区都是并行的,用单线程执行临界区的时间/用单线程执行(临界区+非临界区)的时间就是串行百分比。

    六、总结

    多线程一定就比单线程高校,比如大名鼎鼎的Redis,是基于内存操作的,这种情况下,单线程可以很高效的利用CPU。而多线程的使用场景一般是存在相当比例的I/O或网络操作。

    依据公式先计算,后续结合实际来调优(综合考虑CPU 内存 硬盘读写速度 网路状况等)

    线程一定就比单线程高校,比如大名鼎鼎的Redis,是基于内存操作的,这种情况下,单线程可以很高效的利用CPU。而多线程的使用场景一般是存在相当比例的I/O或网络操作。

    依据公式先计算,后续结合实际来调优(综合考虑CPU 内存 硬盘读写速度 网路状况等)

    盲目增加CPU核数也不一定能解决我们的问题。

    展开全文
  • 对于多线程的理解以及我们为什么要使用多线程
  • Java多线程 - 为什么要使用多线程

    千次阅读 2018-09-30 04:00:53
    Java多线程一:为什么要使用多线程? 我可以总结成一句话:为了效率或者说性能。 我们可以分析一下下面两个场景 第一个场景——拍卖 假设有诸多用户在手机上进行出价,大屏幕显示当前最高价和出价记录,主持人最后...
  • 为什么要使用多线程 执行一个简单的“Hello world”却启动了那么多无关的线程,是不是把简单的问题复杂化了?当然不是,因为正确地使用多线程,总能够给开发人员带来显著的好处,而使用多线程的原因主要有一下几点。...
  • 为什么要使用多线程 简单来讲,就是为了程序运行的更快 1、发挥多处理器的强大能力(见http://www.cnblogs.com/xrq730/p/4850883.html) 现在,多处理器系统正日益盛行,并且价格不断降低,即时在低端服务器和...
  • 所以那为什么要使用多线程呢? 1、充分利用CPU的计算能力 我们的CPU是多核的,闲着也是闲着,为什么不利用起来呢?我们要把CPU的计算能力发挥到极致。线程是大多数操作系统调度的基本单元,一个程序作为一个进程来...
  • 为什么要使用多线程?

    2020-03-31 11:08:44
    从当代互联网发展趋势来说: 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。 再深入到计...
  • 在单核CPU中,多线程主要是为了降低阻塞。 多线程的并发,其实是一种“伪并行”。 在每个时刻,真正执行的只有一个线程。 但是,由于多线程减少了等待IO操作(比如:磁盘、网络、数据库等)时间, 所以,多线程...
  • 为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰.为了处理大量的IO操作时或处理的情况需要花费大量的时间等等,比如:读写文件,视频图像的采集,处理,显示,保存等 多线程的好处: 1.使用线程...
  • 1、什么是线程? 线程是指程序在执行过程中,能够执行程序代码的一个执行单元,在Java语言中,线程有四种状态:运行,就绪,挂起,结束。 2、线程与进程的区别?...3、为什么使用多线程? (1)、使用多线程
  • 使用多线程的场景:  场景一、定时向大量的用户发送邮件。所有的定时任务都是多线程的实现。  场景二、用户注册时候需要短信或则邮件验证。短信和邮件接口比较耗时,前端UI感觉被卡住,这时候 一个异步线程去...
  • 1、什么是线程? 线程是指程序在执行过程中,能够执行程序代码的一个执行单元,在Java语言中,线程有四种状态:运行,就绪,挂起,结束。 2、线程与进程的区别?...3、为什么使用多线程? (1)、使用多线程
  • 多线程 https://www.jianshu.com/p/f30ee2346f9f
  • 线程是指程序在执行过程中,能够执行程序代码的一个执行单元。在Java语言中,线程有四种状态:运行、就绪、挂起和结束。  进程是指一段在执行的程序。而线程有时也被称为轻量级进程,各个线程之间共享程序的内存...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,264
精华内容 2,505
关键字:

为什么要使用多线程