Java 并发编程是一个囊括了多线程、并发、并行(parallelism)的一个java 平台项目。他包括了Java 并发工具,问题,和解决方案。这个Java 并发教程包括了多线程的主要概念,包括关于Java中多线程的并发结构,并发问题,消耗,优点。
Java 并发编程视频教程
如果你更喜欢视频,我录制了一个包括这个教程同样题目的一些视频。你可以在youtube找到视频列表
https://www.youtube.com/playlist?list=PLL8woMHwr36EDxjUoCzboZjedsnhLP1j4
什么是多线程
多线程意味着你在一个程序中有多个线程在运行。一个线程就像一个单独的CPU在执行你的程序,然而,一个多线程的程序就像一个程序有多个CPU同时在执行不同部分的代码。
但是一个线程不等于一个CPU. 通常单个CPU在他的运行期间会在多个线程之间共享,在给定的时间中对各个选择线程选择执行。他也有可能出现某一个程序中的线程被不同CPU执行的情况。
为什么用多线程
这里几个原因解释为什么在一个程序中使用多线程。一些最通常用于解释多线程的原因是:
- 更好利用单个CPU。
- 更好利用过多个CPU 或CPU 核心。
- 对等待相应更好的用户体验
- 对公平性更好的用户体验
我会在接下来的小结中解释这些原因的细节部分。
更好利用单个CPU
其中一个最常用的原因时能够更好的利用电脑的资源。例如,如果一个线程在等待一个请求网络发送结束的回应, 然后另个一个线程也可以同时使用CPU 做一些事情。另外,如果一个电脑有用多个CPU, 或者如果这个CPU 拥有多个核心。多线程操作可以帮助你的应用使用这些余下的CPU 核心。
更好利用多个CPU或者CPU 核心
如果一个电脑包含多个CPU或者一个CPU包含多个执行核心,为了你的应用可以利用到所有的CPU或者CPU 核心,你可以使用多线程。 一个单个的线程可以利用一个CPU, 正如我上面所提到的, 有时不能利用完整的一个CPU。
在响应能力方面有更好的用户体验
另一个使用多线程的原因是因为多线程体用了更好的用户体验。例如,如果你点击在一个GUI点击一个按钮,这个结果在一个请求中发送到里网络中,然后它关系到哪个线程执行这个请求。 如果你使用同一个线程,也会更新这个GUI。然后这个用户可能体验到这个GUI “操作” ,当这个GUI 的线程等待这个请求的回应。 相对来说,这样一个请求可能被一个背景线程去执行。所以这个GUI 线程同时可以被其他用户的请求所开放使用。
在公平性方面有更好的用户体验
第四个原因时在用户中分享一个电脑的资源时更公平。想象在如下场景中,一个服务器接收到客户端的请求, 只有一个线程执行了这些请求。 如果一个客户端发送一个请求,执行这个请求占用了太长的时间,然后所有其他的客户端的请求不需要等待知道这个请求执行结束。每一个客户端的请求被自己的线程所执行,然而一个单独的任务可以完全垄断这个CPU。
多线程 vs 多任务处理
回到以前一个电脑只有单个CPU 的时候,一次只能执行一个单个程序。大多数小型计算机没有足够的能力同时执行多个程序。 所以当时它不能尝试。公平起见,许多年里,许多大型机系统比个人电脑能够一次执行多个程序
多任务处理
之后出现的多任务处理意味着电脑可以同时执行多个程序 (AKA tasks or processes) 。尽管它不是真正的同时。 单个CPU 被不同的程序之间所分享。 这个操作系统可以在运行的程序中进行选择, 在进行选择前短暂的执行它们中的每一个。
在多任务处理中对软件开发着带来了新的挑战。 程序可以不在假定可以拥有所有的CPU时间的所有权,也包括所有的内存或者任何电脑资源。一个“好的市民” 程序应该为了其他程序可以使用资源,所以在他不在使用资源时应该释放所有的资源,
多线程
稍后出现的多线程意味着你可以在同一个程序中同时使用多个线程进行执行。 一个线程的执行可以想象成为一个CPU 正在执行这个程序,当你拥有多个线程执行同一个程序,他就像用多个CPU执行同一个程序。
多线程实现困难
多线程是对提升一些类型的程序的效率是一个有效的方式。然而,多线程比多任务处理更具有挑战性,一个线程在执行同一个程序,因此在同时读写同一个内存,这种到导致在单线程序中看不到的错误。一些错误可能不会在单个CPU机器中发现, 因为两个线程从来不真正 “同时” 执行。 现代的电脑尽管用伴随着多核心CPU, 甚至拥有多个CPU。着意味着分开的线程可以同时被分别的
核心或者CPU所执行。
如果一个线程读取一个内存地址时有另一个线程在写入它时,什么值将会被第一个线程所读取?老的值?还是被第二个线程写入的值?或者是混合的值?或者,如果连个线程同时写入同一个内存地址,什么值将会在他们执行后会留下来?这个值将会被第一个线程写入?这个值将会被第二个线程写入?或者同时写入混合的值?
没有合适的注意事项可能出现任何可能发生的结果。这个行为是不可预测的。这些结果会一次一次的改变。 因此作为一个开发者懂得如何正确的处理这些注意事项时非常重要的。这意味着学习控制线程时如何访问分享资源,像内存,文件,数据库等等。这是一个主要的中心在Java并发课程中。
Java 中多线程和并发
Java 是一个较早把多线程编程变得较为容易的语言。Java 早期就具备多线程的能力。 然而,Java 开发者们经常编队这些问题。这也是我写这个Java 并发教程的原因。对我自己来说,和对任何Java 开发者来说都是有益处的。
并发模型
第一个Java 并发模型假设多个线程在同一个应用中执行也会分享对象。 这个类型的并发模型通常看作一个“分享状态的并发模型”。 一些并发语言结构和设计用来支持这样的并发模型。
然而, 自从第一本Java并发的书籍面世以来甚至从Java 5 并发工具包发布以来,一些在并发结构和设计的世界中发生了许多事情。
分享状态并发模型导致了许多许多难以优雅解决的并发问题。然而,另外一些并发模型指出正如“shared nothing” 或者“separate state” 广受欢迎。在分离状态式并发模型中,线程不分享任何对象或者数据。这避免了许多分享状态式并发模型中的并发访问题。
最新的中,异步 “separate state” 平台和类似Netty 的工具,Vert.x 和 Play/Akka 和Qbit 的出现。发布了新的非阻塞并发算法, 和新的非阻塞工具像 LMax Disrupter 也加入到我们的工具包中。在Java 7 和Java 8 的集合类流API中, 新的函数式并行程序设计出现在Fork 和Join 框架中被提及。
随着所有这些新的发展, 这次我更新这个Java 并发教程。所以, 这个教程又一次成为了半成品,新的教程将会在合适的时机发行。