本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获。由于个人水平有限,不对之处还望矫正!
相同线程是一并发框架模型,是一个单线程系统向外扩展成多个单线程的系统。这样的结果就是多个单线程并行运行。
为什么是单线程系统?
你也许会感到好奇,为什么当今还有人设计单线程系统。单线程系统之所以这么普及,是因为单线程系统相对于多线程并发系统更为简单。单线程系统不需要与其他线程共享任何数据。这就使得单线程系统可以使用非并发的数据结构,可以更好的利用CPU和CPU缓存。
![1240](http://upload-images.jianshu.io/upload_images/5179299-fac73044c18a4588.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
不幸的是,单线程并发系统并不充分利用当今计算机的CPU。现在的计算机一般有2,4或者更多的核,每个核的作用与单个CPU一样,一个单线程并发系统只能利这些核中的一个,单线程系统的结构图如下:
相同的线程、单线程的扩展
为了更为充分的利用CPU,单线程系统可以进行扩展以至于能利用整个计算机资源。
每个CPU一个线程
![1240](http://upload-images.jianshu.io/upload_images/5179299-3dbdf6d3fb79814b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
通常情况下,相同线程只在一个CPU上运行一个线程。如果计算机有4个CPU或是这个CPU拥有4个核,然后他会在4个CPU或是在4个核上运行4个线程实例。其结构图如下 :
无共享状态
单线程系统看起来与多线程系统非常相似。因为,一个单线程系统有多个线程同时运行在系统内部。但是它与多线程系统有一点点的不同。
![1240](http://upload-images.jianshu.io/upload_images/5179299-4248379d38ac35ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
单线程系统与多线程系统的不同之处在于:在单线程系统中,线程间不共享状态。这里没有线程并发的访问共享内存。没有共享数据结构等。它们的不同之处如下图:
缺少共享状态,使得每个线程的行为是一个单线程系统,然而,因为一个单线程系统可以包括多个线程,所以它并不是真正意义上的单线程。因此,我认为将这种模型称之为相同线程的系统更为准确些。而不是叫单线程设计模式的多线程系统,相同的线程更容易理解。
负载分配
显然,一个单线程系统需要将他们的工作负载到单线程远行的实例上。如果不这样做,将会只有一个实例完成所有的工作。那么其实这就是一个单线程。
如何准确分配负载到不同的实例上,这取决于你的系统是如何设计的。
单线程微服务
如果你的系统是由多个微服务组成的。每个微服务是以一个单线程模型运行。当你在同一台机子上发布多个单线程微服务,每个微服务可以在一个CPU上运行一个单线程。
自然而然,微服务不共享任何数据。因此微服务是一个单线程很好的例子。
分片数据服务
如果你的系统确实需要共享数据,或是数据库中最新的数据,你可以对数据库进行分片,分片意味你把一个数据库划分为多个数据库。这些数据是有代表性的分离,例如:属于owner的数据会被插入到相同的数据库。
线程通信
如果相同线程里的线程需要通信,它们需要传递消息。线程A想通过通用的消息(a byte sequence)方式传递到线程B,线程B可以复制这个消息并且进行读取。通过复制这个消息,线程B要确保它在读取这个消息的时候线程A不对其进行修改。
线程间消息通信的结构图如下:
![1240](http://upload-images.jianshu.io/upload_images/5179299-e64c953dca3e05e0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
线程间的通信可用队列、socket等,只要是适合你系统的方式都可以。
更简单的并发模型
每一个运行在它自己线程的系统如果它是单线程的可以使用相同的线程系统去实现。这就意味着相对有共享状态的线程来说内部并发模型变得更加简单了。你不需要担心并发的数据结构以及所有的并发问题。
插图
下面是单线程、多线程、相同线程的插图,通过这些插图,你可以有个清晰的对比。
首先是单线程系统模型:
![1240](http://upload-images.jianshu.io/upload_images/5179299-59efd2f165f1c861.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
其次是多线程模型:
![1240](http://upload-images.jianshu.io/upload_images/5179299-28b3b396294b30e0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后是多线程模型:
![1240](http://upload-images.jianshu.io/upload_images/5179299-62430d1db943443d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)