多线程在web中的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fengyuhan123/article/details/82883797

整理网络上的

最典型的如:
1、用户注册完成送大礼包/积分之类,且积分等也是另一个系统并比较耗时;
且这类任务即使失败也不是特别重要的。

2、后台线程:比如定期执行一些特殊任务,如定期更新配置文件,任务调度(如quartz),一些监控用于定期信息采集等。

回答二:
最典型的应用比如tomcat,tomcat内部采用的就是多线程。
上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。
如果不采用多线程机制,上百个人同时访问一个web应用的时候,tomcat就得排队串行处理了,那样客户端根本是无法忍受那种访问速度的。

还有就是需要异步处理的时候,需要使用多线程。
比如task a和task b要并行处理,单个线程只能串行处理,先做完task a然后再做task b。

如果想要多个task同时执行的话,就必须为每个task分配一个线程,然后通过java虚拟机的线程调度,来同时执行多个任务。

比如你的CPU是多核心的话,就可以让一个CPU执行一个线程。
如果只有一个CPU的话,底层是按照分时复用的原则,各个线程按照时间片来获得CPU资源。

回答三:

特别耗时的操作

如备份数据库,可以开个线程执行备份,然后执行返回,前台不断向后台询问线程执行状态问

JAVA项目中哪些场景需要用到多线程,深感迷茫,请使用过的高手指点。

场景一:
一个业务逻辑有很多次的循环,每次循环之间没有影响

比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。

这时可以用多线程,将1万条URL分成50等份,开50个线程,每个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。

场景二:

需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。

总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。

不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级

因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!

最典型的如:1、用户注册完成送大礼包/积分之类,且积分等也是另一个系统并比较耗时;且这类任务即使失败也不是特别重要的。2、后台线程:比如定期执行一些特殊任务,如定期更新配置文件,任务调度(如quartz),一些监控用于定期信息采集等。回答二:最典型的应用比如tomcat,tomcat内部采用的就是多线程,上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。如果不采用多线程机制,上百个人同时访问一个web应用的时候,tomcat就得排队串行处理了,那样客户端根本是无法忍受那种访问速度的。还有就是需要异步处理的时候,需要使用多线程。比如task a和task b要并行处理,单个线程只能串行处理,先做完task a然后再做task b。如果想要多个task同时执行的话,就必须为每个task分配一个线程,然后通过java虚拟机的线程调度,来同时执行多个任务。比如你的CPU是多核心的话,就可以让一个CPU执行一个线程。如果只有一个CPU的话,底层是按照分时复用的原则,各个线程按照时间片来获得CPU资源。回答三:特别耗时的操作,如备份数据库,可以开个线程执行备份,然后执行返回,前台不断向后台询问线程执行状态问:JAVA项目中哪些场景需要用到多线程,深感迷茫,请使用过的高手指点。答:场景一:一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。场景二:需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!


有一些比较耗时,但又很重复的工作可以多线程。

比如入库,入库时很耗时的。但如果入库的数据已准备好,并且很多。多线程就好一些。

比如同步数据,你不知道什么时候对方会给你传递数据过来,这个时候你就间隔一段时间让他自己去执行,其实还涉及一些逻辑上的处理比较耗的。这样不影响你其他地方的处理……

(1)线程的工作场景主要有两条:
一个是并发操作,避免阻塞和更有效利用资源。典型的例子有:在长时间工作的程序中使用工作线程避免界面失去响应。在网络下载程序中,使用多个线程提高对网络的使用效率,更快下载文件。
一个是并行,线程是处理器调度的最小单位。如果你的计算机配置了多个处理器或者内核,那么可以同时利用多个处理器同时计算,加快问题解决的速度。
(2)多线程的工作原理:
对于单处理器系统,操作系统会轮流调度每个线程执行一小段时间,然后切换另一个线程,在切换的时候,保存当前线程使用的寄存器上下文和堆栈,并且在下次调度的时候恢复。这样线程中的程序感觉不到自己被中断过。对于多处理器系统,操作系统会将不同的线程调度给多个处理器,让它们并行执行。

这个要用,由很多可用的,看你的程序结构,发邮件是一个,假如你的文档管理系统要做全文索引,那么在用户上传一个文件后,后台要做索引,就可以启动一个线程去创建索引,还有如果你的文档管理系统权限比较复杂,涉及文件夹父子关系权限的继承和覆盖等复杂的ACL操作,都可以使用多线程。

1、单线程和多线程区别:
单线程处理的优点:同步应用程序的开发比较容易,但由于需要在上一个任务完成后才能开始新的任务,所以其效率通常比多线程应用程序低,如果完成同步任务所用的时间比预计时间长,应用程序可能会不响应。
多线程处理可以同时运行多个过程,简单说下多线程开发的益处:
1.多线程开发可以将耗时操作放入子线程,将UI刷新加入主线程,防止页面卡顿。
2.在并发操作时使用多线程,如C/S架构的服务器端并发线程响应用户的请求。
3.在多核CPU系统中,使用线程可以提高程序响应速度,提高CPU和内存的利用率。
4.改善程序结构。将一个复杂的的进程分为多个线程,减少类之间的耦合。
5.将程序分块管理,方便程序的开发和维护。
6.可以随时停止任务。 可以分别设置各个任务的优先级以优化性能。
2、开启多线程
一个请求就是一个线程,这个线程不需要我们来控制,WEB容器自己实现,这是第一个应用。
我们也可以在web中new线程来做我们的事。比如,当我有一个很耗时的操作,像统计排名之类的功能。当用户在web上点击排名时,由于这个计算量太大,可能要计算3~5分钟或更久。这时我们会在servlert中new一个线程来做这个事情,这样用户就可以点击排名后去做其他的事,等排名出来现通知他。如果不new线程当用户点排名时,浏览器就会一直卡在这里,一个圈圈转啊转的,就是不出来。所以我们可以new线程来做耗是任务。还有很多比如,定时任务、WEB版的爬虫程序、监听等
3、场景一:一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。
场景二:需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。
场景三:电商项目中controller层需要接收前台传来的需要下架商品id,因为是全选操作所以也就是数据库中商品表的所有id。然后调用service层业务逻辑进行删除。本人数据库中商品表大概有3000条数据,在不考虑多线程方式下,速度已经明显受到影响,实际项目中又何止成千上万条数据!如果单线程逐一进行删除其性能可想而知。所以考虑创建多个线程,多线程并发形式执行商品下线业务逻辑。
总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!

为什么要使用多线程?
1.防止阻塞主线程,提高吞吐量
2,提高资源的利用率
应用场景:
1,最典型的应用比如tomcat,tomcat内部采用的就是多线程,上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。

2,做登录业务时使用到sms短信网关业务,创建子线程,让子线程去调用sms服务,主线程则返回,这样做可以提高用户的体验度
3,图片上传业务
4

项目中如何使用多线程
多线程在项目中主要用来解决并发任务执行。java中线程的主要实现方式有三种:继承Thread类 实现Runnable接口 实现Callable接口。另外还可以通过Executor类来创建多线程线程池。
线程生命周期:首先通过继承thread或者实现runnable接口来创建一个线程,当调用线程的start方法,线程进入就绪状态,如果这时处理器有资源运行此线程,线程就进入运行状态,如果线程内部调用了sleep就会放弃cpu资源,返回到阻塞状态,线程等待某个通知,sleep时间到了之后,如果其他线程发送通知,那么当前线程就从阻塞状态变为就绪状态恢复执行。另如果调用了yield()方法也会从运行状态变为就绪状态。一般来说线程执行完毕或者调用stop方法线程结束生命周期。
四种模板线程池:1可缓存线程池 newCachedThreadPool 2定长线程池 newFixedThreadPool 3定长支持定时及周期性任线程池, newScheduledThreadPool 4单线程化的线程池(有序) newSingleThreadExecutor 。我们在项目中主要使用了第二种就是定长线程池newFixedThreadPool,一般多线程进行并行任务处理需要配合队列使用。队列中存放任务信息,当线程池中的线程进行任务处理,主动去队列领取任务,队列将任务弹出并交由线程执行,所有线程谁先执行完,就领取行的任务,直到队列中没有任务。
线程安全:一般通过加锁解决安全问题,保证数据一致性。一般我们可以使用synchronized标记方法或者代码块,来保证原子性操作。但是synchronized性能不如volatile。 在java底层中一些设计线程安全的源码都是用了volatile关键字。多线程如果要保证数据安全必须要保证原子性、可见性以及有序性。一般情况下当多个线程同时执行时,如果多个线程同时访问同一变量,如果变量所在方法没有使用synchronized,将导致每个线程只关注自己线程内cache的变量值,当多个线程将变量同步到主线程的主存时,会发生数据不一致的情况。如果使用volatile可以让变量拥有可见性,多个线程进行执行时,每个线程都会看到主线程中的主存的变量值发生的改变,进行修正,保证与自己线程数据同步,在线程修改变量时,volatile关键字会强制将修改的值立即写入主存,其他线程中的对应缓存变量就会被强制标记为无效,而从主存中进行同步。

项目业务场景:
批量页面静态化 在系统中,商品详情页我们使用freemarker来进行页面静态化,每天夜里12点开始要对所有商品页面进行一遍静态化,由于商品数量比较多 如果使用单线程将耗时过长,我们使用一个定长线程池进行批量执行,将任务放在队列中,多个线程同时领取并执行。

订单处理(用户下单后可能支付状态不明确,我们后台可以通过多线程去主动核实第三方支付状态,来更新我们系统的订单状态)
登录后用户信息处理(用户登录后应该通知各相关系统将用户常用数据进行缓存 以快速响应登录用户),

大CC的博客

内容目录:
多进程模型多线程模型选用参考

多线程和多进程模型的选用
这里的线程指通过linux的pthread_create而产生的原生线程,线程资源很宝贵,能被操作系统的任务调度器看见的(不是python gevent、go gorouine里的概念);
我们讨论以下两种模型;
多进程单线程模型(以下简称为多进程);单进程多线程模型(以下简称为多线程);多进程模型
优点
编程相对容易;通常不需要考虑锁和同步资源的问题。
更强的容错性:比起多线程的一个好处是一个进程崩溃了不会影响其他进程。
有内核保证的隔离:数据和错误隔离。
对于使用如C/C++这些语言编写的本地代码,错误隔离是非常有用的:采用多进程架构的程序一般可以做到一定程度的自恢复;(master守护进程监控所有worker进程,发现进程挂掉后将其重启)
多进程的案例
nginx主流的工作模式是多进程模式(也支持多线程模型)
几乎所有的web server服务器服务都有多进程的,至少有一个守护进程配合一个worker进程,例如apached,httpd等等以d结尾的进程包括init.d本身就是0级总进程,所有你认知的进程都是它的子进程;
chrome浏览器也是多进程方式。
redis也可以归类到“多进程单线程”模型(平时工作是单个进程,涉及到耗时操作如持久化或aof重写时会用到多个进程)
多线程模型
优点
多线程优点:创建速度快,方便高效的数据共享
共享数据:多线程间可以共享同一虚拟地址空间;多进程间的数据共享就需要用到共享内存、信号量等IPC技术;
较轻的上下文切换开销 - 不用切换地址空间,不用更改寄存器,不用刷新TLB。
提供非均质的服务
如果全都是计算任务,但每个任务的耗时不都为1s,而是1ms-1s之间波动;这样,多线程相比多进程的优势就体现出来,它能有效降低“简单任务被复杂任务压住”的概率;
适用的场景
1 线程间有数据共享,并且数据是需要修改的(不同任务间需要大量共享数据或频繁通信时);
2 提供非均质的服务(有优先级任务处理)事件响应有优先级;
3 单任务并行计算,在非CPU Bound的场景下提高响应速度,降低时延;
4 与人有IO交互的应用,良好的用户体验(键盘鼠标的输入,立刻响应)
多线程案例
桌面软件,响应用户输入的是一个线程,后台程序处理是另外的线程;
memcached
选用
单进程多线程和多进程单线程,2种模式如何取舍?
进程线程间创建的开销不足作为选择的依据,因为一般我们都是使用线程池或者进程池,在系统启动时就创建了固定的线程或进程,不会频繁的创建和销毁;
首先,根据工作集(需要共享的内存)的大小来定;如果工作集较大,就用多线程,避免cpu cache频繁的换入换出;比如memcached缓存系统;
其次,选择的依据根据以上多线程适用的场景来对比自身的业务场景,是否有这样场景需求:数据共享、提供非均质的服务,单任务拆散并行化等;
如果没有必要,或者多进程就可以很好的胜任,就多用多进程,享受单线程编程带来便利;
RCU的发明者,Paul McKenny 在《Is Parallel Programming Hard, And, If So, What Can You Do About It?》说过:
能用多进程方便的解决问题的时候不要使用多线程。
参考
ref:《Linux多线程服务端编程:使用muduo网络库》
ref:http://www.zhihu.com/question/19903801
ref:https://computing.llnl.gov/tutorials/pthreads/#WhyPthreads


本文来自 RoyKuang07 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/pirlck/article/details/52296716?utm_source=copy

本文来自 Xiayubing_ 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/Xiayubing_/article/details/81381704?utm_source=copy

本文来自 袖扣 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/Sundefind/article/details/79062239?utm_source=copy

本文来自 fmwind 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/fmwind/article/details/77068706?utm_source=copy
参考链接

https://blog.csdn.net/kangkang_hacker/article/details/80863359?utm_source=copy

猜你喜欢

转载自blog.csdn.net/fengyuhan123/article/details/82883797