0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

公司项目中Java的多线程一般用在哪些场景?

Android编程精选 来源:Android编程精选 2023-02-10 11:47 次阅读
多线程使用的主要目的在于:1、吞吐量:你做WEB,容器帮你做了多线程,但是他只能帮你做请求层面的。简单的说,可能就是一个请求一个线程。或多个请求一个线程。如果是单线程,那同时只能处理一个用户的请求。2、伸缩性:也就是说,你可以通过增加CPU核数来提升性能。如果是单线程,那程序执行到死也就利用了单核,肯定没办法通过增加CPU核数来提升性能。 鉴于是做WEB的,第1点可能你几乎不涉及。那这里我就讲第二点吧。

举个简单的例子:

假设有个请求,这个请求服务端的处理需要执行3个很缓慢的IO操作(比如数据库查询或文件查询),那么正常的顺序可能是(括号里面代表执行时间):
  1. 读取文件1 (10ms)
  2. 处理1的数据(1ms)
  3. 读取文件2 (10ms)
  4. 处理2的数据(1ms)
  5. 读取文件3 (10ms)
  6. 处理3的数据(1ms)
  7. 整合1、2、3的数据结果 (1ms)
单线程总共就需要34ms。 那如果你在这个请求内,把ab、cd、ef分别分给3个线程去做,就只需要12ms了。 所以多线程不是没怎么用,而是,你平常要善于发现一些可优化的点。然后评估方案是否应该使用。假设还是上面那个相同的问题:但是每个步骤的执行时间不一样了。
  1. 读取文件1 (1ms)
  2. 处理1的数据(1ms)
  3. 读取文件2 (1ms)
  4. 处理2的数据(1ms)
  5. 读取文件3 (28ms)
  6. 处理3的数据(1ms)
  7. 整合1、2、3的数据结果 (1ms)
单线程总共就需要34ms。 如果还是按上面的划分方案(上面方案和木桶原理一样,耗时取决于最慢的那个线程的执行速度),在这个例子中是第三个线程,执行29ms。那么最后这个请求耗时是30ms。比起不用单线程,就节省了4ms。但是有可能线程调度切换也要花费个1、2ms。因此,这个方案显得优势就不明显了,还带来程序复杂度提升。不太值得。 那么现在优化的点,就不是第一个例子那样的任务分割多线程完成。而是优化文件3的读取速度。可能是采用缓存和减少一些重复读取。 首先,假设有一种情况,所有用户都请求这个请求,那其实相当于所有用户都需要读取文件3。那你想想,100个人进行了这个请求,相当于你花在读取这个文件上的时间就是28×100=2800ms了。那么,如果你把文件缓存起来,那只要第一个用户的请求读取了,第二个用户不需要读取了,从内存取是很快速的,可能1ms都不到。

伪代码:


		
			publicclassMyServletextendsServlet{ privatestaticMapfileName2Data=newHashMap(); privatevoidprocessFile3(StringfName){ Stringdata=fileName2Data.get(fName); if(data==null){ data=readFromFile(fName);//耗时28ms fileName2Data.put(fName,data); } //processwithdata } }
			看起来好像还不错,建立一个文件名和文件数据的映射。如果读取一个map中已经存在的数据,那么就不不用读取文件了。
			可是问题在于,Servlet是并发,上面会导致一个很严重的问题,死循环。因为,HashMap在并发修改的时候,可能是导致循环链表的构成!!!(具体你可以自行阅读HashMap源码)如果你没接触过多线程,可能到时候发现服务器没请求也巨卡,也不知道什么情况!
			好的,那就用ConcurrentHashMap,正如他的名字一样,他是一个线程安全的HashMap,这样能轻松解决问题。

		
			publicclassMyServletextendsServlet{ privatestaticConcurrentHashMapfileName2Data=newConcurrentHashMap(); privatevoidprocessFile3(StringfName){ Stringdata=fileName2Data.get(fName); if(data==null){ data=readFromFile(fName);//耗时28ms fileName2Data.put(fName,data); } //processwithdata } }
			这样真的解决问题了吗,这样虽然只要有用户访问过文件a,那另一个用户想访问文件a,也会从fileName2Data中拿数据,然后也不会引起死循环。最新 Java 面试题出炉!分享给你。
			可是,如果你觉得这样就已经完了,那你把多线程也想的太简单了,骚年!你会发现,1000个用户首次访问同一个文件的时候,居然读取了1000次文件(这是最极端的,可能只有几百)。What the ***in hell!!!
			难道代码错了吗,难道我就这样过我的一生!
			好好分析下。Servlet是多线程的,那么

		
			publicclassMyServletextendsServlet{ privatestaticConcurrentHashMapfileName2Data=newConcurrentHashMap(); privatevoidprocessFile3(StringfName){ Stringdata=fileName2Data.get(fName); //“偶然”--1000个线程同时到这里,同时发现data为null if(data==null){ data=readFromFile(fName);//耗时28ms fileName2Data.put(fName,data); } //processwithdata } }
			上面注释的“偶然”,这是完全有可能的,因此,这样做还是有问题。
			因此,可以自己简单的封装一个任务来处理。

		
			publicclassMyServletextendsServlet{ privatestaticConcurrentHashMapfileName2Data=newConcurrentHashMap(); privatestaticExecutorServiceexec=Executors.newCacheThreadPool(); privatevoidprocessFile3(StringfName){ FutureTaskdata=fileName2Data.get(fName); //“偶然”--1000个线程同时到这里,同时发现data为null if(data==null){ data=newFutureTask(fName); FutureTaskold=fileName2Data.putIfAbsent(fName,data); if(old==null){ data=old; }else{ exec.execute(data); } } Stringd=data.get(); //processwithdata } privateFutureTasknewFutureTask(finalStringfile){ returnnewFutureTask(newCallable(){ publicStringcall(){ returnreadFromFile(file); } privateStringreadFromFile(Stringfile){return"";} } } }
			以上所有代码都是直接在bbs打出来的,不保证可以直接运行。
			多线程最多的场景:web服务器本身;各种专用服务器(如游戏服务器);

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    12

    文章

    8701

    浏览量

    84563
  • JAVA
    +关注

    关注

    19

    文章

    2943

    浏览量

    104107
  • 多线程
    +关注

    关注

    0

    文章

    275

    浏览量

    19850

原文标题:面试官:公司项目中Java的多线程一般用在哪些场景?

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Java多线程的用法

    本文将介绍Java多线程的用法。 基础介绍 什么是多线程 指的是在个进程中同时运行多个线程
    的头像 发表于 09-30 17:07 844次阅读

    多线程编程之: 问题提出

    :lpThreadAttributes:指向个 SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为 NULL; dwStackSize:指定了线程
    发表于 10-22 11:41

    Java直独得恩宠的秘诀

    Java中没有指针,这样就没有办法直接访问内存了。另外Java也不容易出现内存泄露。而且Java确实有很多企业在用,都是用在项目上。这就意
    发表于 09-28 14:24

    请问SPI接口一般都是用在哪里的?

    SPI接口一般都是用在哪里的?如何用?
    发表于 09-25 05:55

    Java基础学习多线程使用指南

    黑马程序员-----Java基础学习多线程
    发表于 10-08 14:10

    java多线程编程实例 (源程序)

    java多线程编程实例 import java.awt.*;import javax.swing.*; public class CompMover extends Object { 
    发表于 10-22 11:48 0次下载

    java多线程设计模式_结城浩

    JAVA多线程设计模式》通过浅显易懂的文字与实例来介绍JAVA线程相关的设计模式概念,并且通过实际的JAVA程序范例和UML图示来一一解说
    发表于 01-05 16:15 0次下载
    <b class='flag-5'>java</b><b class='flag-5'>多线程</b>设计模式_结城浩

    Java多线程总结之Queue

    Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为 阻塞队列和非阻塞队列 ,其中阻塞队列的典型例子
    发表于 11-28 16:14 3246次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>多线程</b>总结之Queue

    java学习——java面试【事务、锁、多线程】资料整理

    本文档内容介绍了基于java学习java面试【事务、锁、多线程】资料整理,供参考
    发表于 03-13 13:53 0次下载

    涤纶电容一般用在哪里?

    二者是有区别的!涤纶电容又叫聚酯电容符号为CL,电容量一般40p--4μ, 额定电压63--630V,主要特点体积小容量大耐热耐湿但稳定性差一般用在对稳定性和损耗要求不高的低频电路。
    发表于 11-13 09:51 3943次阅读

    EEPROM 在项目中一般会做几项特殊操作

    EEPROM,在项目中一般会做几项特殊操作
    的头像 发表于 03-04 14:01 2967次阅读
    EEPROM 在<b class='flag-5'>项目中</b>我<b class='flag-5'>一般</b>会做几项特殊操作

    Java多线程永动任务 多线程异步任务项目解读

    , 这个示例的原型是公司自研的多线程异步任务项目 ,我把里面涉及到多线程的代码抽离出来,然后进行定的改造。 里面涉及的知识点非常多,特别适
    的头像 发表于 10-19 11:46 996次阅读

    多线程编程可以应用在哪里?C++多线程详解

    多线程并发指的是在同个进程中执行多个线程。 优点: 有操作系统相关知识的应该知道,线程是轻量级的进程,每个线程可以独立的运行不同的指令序列
    发表于 04-13 10:10 618次阅读

    纽扣型超级电容器一般用在哪里?

    纽扣型超级电容器一般用在哪里?即便是同种类型的产品,其型号、规格以及作用都是不同的。所以,大家在选择产品的时候,也要从细节方面来考虑。纽扣型超级电容器在市场上是很常见的,它被应用在
    的头像 发表于 02-24 10:33 1602次阅读
    纽扣型超级电容器<b class='flag-5'>一般</b>是<b class='flag-5'>用在哪</b>里?

    java实现多线程的几种方式

    Java实现多线程的几种方式 多线程是指程序中包含了两个或以上的线程,每个线程都可以并行执行不同的任务或操作。
    的头像 发表于 03-14 16:55 437次阅读