即使编写多线程程序具有挑战性,但它仍在使用中,是因为它可以带来如下的好处:

  • 更好的资源利用
  • 在某些场景下程序的设计会更简单
  • 提升程序的响应性

更好的资源利用

假设一个应用会从本地文件系统中读取和处理文件。我们假设从磁盘上读取一个文件花费5秒钟并且处理它会花费2秒钟。那么处理两个文件会花费:

 seconds reading file A
seconds processing file A
seconds reading file B
seconds processing file B
-----------------------
seconds total

从磁盘上读取文件的时候,大多数的CPU时间都会花费在等待磁盘来读取数据。在这个时候CPU是相当空闲的。在这个时候它可以干点别的事情。通过改变操作的顺序,CPU可以得到更好的利用。看一下下面的这种操作顺序:

 seconds reading file A
seconds reading file B + seconds processing file A
seconds processing file B
-----------------------
seconds total

CPU会等待第一个文件的读取。然后他开始读取第二个文件。当第二个文件正在被读取的时候,CPU可以处理第一个文件。注意,当等待文件从磁盘上读取的时候,CPU大多数是空闲的。

一般来说,CPU可以在等待IO操作的时候做一些其他的事情。当然不一定只是磁盘IO会阻塞,网络IO也会阻塞,或者等待来自机器中一个用户的输入。网络和磁盘的IO经常比CPU和内存的IO慢得多。

更简单的程序设计

如果你准备编写通过在单线程应用中手工操作文件的读取和操作顺序的程序,你就必须要跟踪每个文件读取和处理的状态。相反,你可以启动两个线程,每个线程仅仅只读取或者处理单个文件。这两个线程都会因为等待磁盘读取文件而阻塞。在等待的时候,其他的线程可以使用CPU来处理它们已经读取的那部分文件。结果就是,磁盘一直会处于忙碌状态,把不同的文件读到内存中。这样可以带来更好的磁盘和CPU的利用。这样的程序更容易编写,因为每个线程仅仅需要跟踪单个文件。

提升程序的响应性

将单线程应用转为多线程应用另一个主要目的是为了使应用响应更好。假设一个服务器应用会在某个端口监听即将到来的请求。当接收到请求的时候,它会处理请求然后继续回去监听。服务器的循环可以抽成这样的:

while(server is active){
listen for request
process request
}

如果要花很长的时间去处理请求的话,那么在这期间就没有新的客户端可以发送请求到服务器了。只有服务器在监听的时候才可以接收请求。

另一种设计是把监听线程的请求传给后台的工作线程,然后立即转回去监听。工作线程将会处理请求并给客户端发送响应。这种设计是:

while(server is active){
listen for request
hand request to worker thread
}

这种情况下,服务器线程会更快地监听请求。就有更多地客户端可以向服务器发送请求。服务器因此而更具有响应性。

对于桌面应用也是这样的。如果你点击一个按钮开启一个耗时很长的任务,并且执行任务的线程同时也是更新窗口,按钮等的线程,那么应用会在处理任务的时候表现得响应性很差。其实可以把任务交给后台的线程。当后台线程繁忙地处理任务地时候,窗口线程可以继续响应用户其他地请求。当工作线程把任务处理完毕之后,可以给窗口线程发送信号。这时,窗口线程可以根据任务处理的结果来更新应用窗口。采用后台线程程序可以对用户表现得更具有更好得响应。

Java并发(二)多线程的好处的更多相关文章

  1. Java并发与多线程教程(2)

    Java同步块 Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(synchronzied) ...

  2. Java并发与多线程教程(1)

    Java并发性与多线程介绍 在过去单CPU时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程.虽然并不是真正意义上的“同一时间点”,而是多个任务 ...

  3. java并发与多线程面试题与问题集合

    http://www.importnew.com/12773.html     https://blog.csdn.net/u011163372/article/details/73995897    ...

  4. Java并发和多线程(一)基础知识

    1.java线程状态 Java中的线程可以处于下列状态之一: NEW: 至今尚未启动的线程处于这种状态. RUNNABLE: 正在 Java 虚拟机中执行的线程处于这种状态. BLOCKED: 受阻塞 ...

  5. Java 并发和多线程(一) Java并发性和多线程介绍[转]

    作者:Jakob Jenkov 译者:Simon-SZ  校对:方腾飞 http://tutorials.jenkov.com/java-concurrency/index.html 在过去单CPU时 ...

  6. Java并发和多线程:序

      近期,和不少公司的"大牛"聊了聊,当中非常多是关于"并发和多线程"."系统架构"."分布式"等方面内容的.不少问题, ...

  7. Java并发和多线程2:3种方式实现数组求和

    本篇演示3个数组求和的例子. 例子1:单线程例子2:多线程,同步求和(如果没有计算完成,会阻塞)例子3:多线程,异步求和(先累加已经完成的计算结果) 例子1-代码 package cn.fansuni ...

  8. Java并发和多线程1:并发框架基本示例

    Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括ThreadPool,Executor,Executors,ExecutorService,Com ...

  9. Java并发(二):基础概念

    并发编程的第二部分,先来谈谈发布(Publish)与逸出(Escape); 发布是指:对象能够在当前作用域之外的代码中使用,例如:将对象的引用传递到其他类的方法中,对象的引用保存在其他类可以访问的地方 ...

  10. Java并发和多线程3:线程调度和有条件取消调度

    在第1篇中"并发框架基本示例",提到了Executors和ThreadPool.其中,还有个"定时调度"的方法,Executors.newScheduledTh ...

随机推荐

  1. Android 线性布局(LinearLayout)相关官方文档 - 指南部分

    Android 线性布局(LinearLayout)相关官方文档 - 指南部分 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用 ...

  2. JavaScript 设计模式之建造者模式

    一.建造者模式概念解读 1.建造者模式概念文字解读 建造者模式可以将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示.也就是说如果我们用了建造者模式,那么用户就需要指定需要建造的类 ...

  3. UltraEdit打开中文乱码

    http://hellofs.blog.51cto.com/6109153/1187548 UltraEdit很强大,但是今天发现在打开含有中文的文本时会乱码,还是在配置里找找相关的设置,可以在如图的 ...

  4. Es6 函数式编程 MayBe函子的简单示例

    初级函子的作用非常简单,使用场景主要体现在:深入访问object的属性的时候,不会担心由于属性不存在.undefined.null等问题出现异常. MayBe.js var MayBe = funct ...

  5. C# ASE加密解密

    项目中比较常用的加密手段 /// <summary> /// ASE_128_ECB_无填充_64Base_加密函数 /// </summary> /// <param ...

  6. mysql-5.7 收缩系统表空间详解

    innodb 系统表空间是一个逻辑上的概念,它的物理表现就是innodb系统表空间文件:在讲扩展系统表空间时我们说到 可以用增加文件,增加autoextend标记 这两种方式来解决:但是问题到了收缩表 ...

  7. 修改easyui的easyloader的默认css目录路径

    easyloader默认情况下会使用js文件所在目录下的themes文件夹中的css,这里改成项目自定义的css文件夹. 首先找到: var m=src.match(/easyloader\.js(\ ...

  8. QWidget子窗口中setStyleSheet无效,解决方法

    继承 QWidget setStyleSheet无效,解决方法. 发现 继承自QWidget的自定义类 ,使用setStyleSheet无效, 如果删除头文件中的 Q_OBJECT,setStyleS ...

  9. js动态给table添加/删除tr的方法

    js动态给table添加/删除tr的方法. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> ...

  10. JMeter学习笔记(六)-负载与监听

    1. 场景设计 场景设计的原则:忠于用户实际操作,组合用户的各种操作到场景中来. JMeter场景主要通过线程组设置来完成的,对于复杂场景还需要与逻辑控制器配合完成. 2.场景设置 JMeter线程组 ...