Java并发模型(一)

学习资料来自http://ifeve.com/java-concurrency-thread-directory/java

1、多线程数据库

  1. 进程和线程的区别: 一个程序运行至少一个进程,一个进程至少包含一个线程。
  2. 多线程: 多线程使得在一个程序内部可以拥有多个线程并行执行,一个线程的执行能够被认为是一个cpu在执行该程序,当一个程序运行在多线程下,就好像有多个CPU在同时执行该程序。

多线程在同一个程序内部并发执行,所以会对相同的内存空间进行并发读写操做。编程

思考: 服务器

  1. 若是一个线程在读一个内存时,另外一个线程正向该内存进行写操做,那么进行读操做的线程将得到什么结果呢?是写操做以前的旧值?仍是写操做成功以后的新值?或者一半新一半旧的值?
  2. 若是两个线程同是写一个内存,在操做完成以后又是什么结果呢?是第一个线程写入的值?仍是第二个线程写入的值?仍是两个线程共同写入的一个混合值?

 

2、多线程的优势数据结构

1、资源利用率更好多线程

           好比CPU在等待磁盘读取的时间很是空闲,能够利用这一段时间去作一些其余的事情。并发

2、程序设计在某些状况下更简单负载均衡

           好比单线程去操做两个文件的读取和处理,须要记录每一个文件的读取和处理状态。相反,若是用两个线程分别处理一个文件,一个线程在读取的时候就会阻塞另外一个线程,此时,被阻塞的线程就能够去执行处理的操做。不但提高磁盘和CPU利用率,编程也更加容易实现。异步

3、程序响应更快分布式

           例如服务器在某一个端口监听进来的请求,当一个请求到来时它去处理这个请求,处理完了再返回去监听其余请求。假设这个请求须要占用大量的时间呢?

           另外一种方式是服务器监听线程把进来的请求传递给工做者线程,而后立刻返回去监听,这样就可以接受和处理更多客户端发送过来的请求,服务的响应也更快了。

3、多线程的代价

         1、设计更复杂

         通常来讲,多线程应用程序比单线程应用程序更加复杂,在多线程访问共享数据的时候,线程之间的交互每每很是复杂,不正确的线程同步产生的错误很是难以被发现,而且重现以修复。

         2、上下文切换的开销

         当CPU执行一个线程切换到执行另一个线程的时候,它须要先存储当前线程的本地数据、程序指针等,而后载入另外一个线程的本地数据、程序指针等,最后才开始执行。这种切换叫作上下文切换(context switch),CPU会在一个上下文(context)中执行一个线程,而后切换到另外一个上下文(context)执行另一个线程。

         若是没有必要应该尽可能减小上下文的切换。

         3、增长资源消耗

         除了CPU,线程还须要一些内存来维持它本地的堆栈,也须要占用操做系统中一些资源来管理线程。咱们能够写一个程序建立100个线程,而后这些线程只是等待什么都不作,而后看看占用了多少内存。

4、并发编程模型

         并发编程模型指定了系统中的多线程如何经过协做来完成分配给它们的做业,不一样的并发模型采用不一样的方式拆分做业,同时线程间的协做和交互方式也不相同。

一、 并发模型与分布式系统之间的类似性

并发模理相似于分布式系统中使用的不少体系结构,在分布式系统中进程之间能够

通讯(进程可能在不一样的机器中),在并发系统中线程之间也能够相互通讯。例如为工做者们(线程)分配做业的模型通常与分布式系统中的负载均衡系统比较类似。

二、 并行工做者

委托者将传入的做业被分配给不一样的工做者上,每一个工做者完成整个任务,工做者们运做在不一样的线程上,甚至可能在不一样的CPU上。

 

优势:容易理解,只须要添加更多的工做者来提升系统的并行度。

缺点:

  1. 并发工做者一般须要访问一些共享数据,不管是内存中仍是数据库中,一旦涉及到共享状态状况就会变得复杂。线程须要以某种方式存取共享数据,以确保某个线程的修改可以对其余线程可见。线程须要避免竟态、死锁以及不少其余共享状态的并发问题。

等待访问共享数据时,线程之间的互相等待会丢失部分并行性,许多并发数据结构是阻塞的,意味着在某个时刻只有一个或者不多的线程能访问,致使共享数据出现竞争状态,出现必定串行化。

  1. 无状态的工做者: 共享状态可以被其余线程修改,因此工做者在每次须要的时候必须重读状态,以确保每次都能访问到最新的副本。工做者没法在内部保存这个状态称为无状态的。特别是状态保存在外部数据库中的时候,每次重读会致使速度变慢。
  2. 任务顺序是不肯定的: 做业A可能在做业B以前就被分配工做者了,可是做业B反而有可能在做业A以前执行,也就是没法保证哪一个做业最早或者最后被执行。

 

三、  流水线模型

也叫反应器系统、事件驱动系统或者无共享模型。

 

相似于工厂生产线上的工人们,每一个工做者只负责做业中的部分工做,当完成了本身这部分工做就转发给下一个工做者,每一个工做者在本身的线程中运行,并不会和其余工做者共享状态。

在实际中可能会有多个不一样的虚拟流水线同时动做,现实多是这样的状况。

 

Actors和Channels

Actors模型中每一个工做者都被称为actor。Actor之间能够直接异步地发送和处理消息,actor能够用来实现一个或多个前面描述的那种做业处理流水线。

 

Channel模型中,工做都之间不直接进行通讯。相返,它们在不一样的通道中发布本身的消息(事件)。其余工做者能够在这些通道上监听消息,发送者无需知道谁在监听。

 

流水线模型的优势:

  1. 无需共享的状态
  2. 有状态的工做者
  3. 较好的硬件整合
  4. 合理的做业顺序

流水线模型的缺点:

  1. 做业执行每每分布到多个工做者上,并所以分布到项目中的多个类上。这样致使在追踪某个做业到底被什么代码执行时变得困难。
  2. 加大了代码编写的难度,有时工做者的代码须要写成回调处理的形式。若在代码中嵌入过多的回调处理,每每会出现所谓的回调地狱(callback hell)现像。

四、  函数式执行(Functional Parallelism)

函数式并行的基本思想是采用函数调用实现程序,函数被看做是代理人(agents)或者actor, 函数之间能够像流水线模型(AKA反应器或者事件驱动系统)那样互相发送消息。

         思考:使用哪一种并发模型好呢?

         一般状况下,这个答案取决于你的系统打算作什么。若是你的做业自己就是并行的、独立的而且没有必要共享状态,你可能会使用并行工做者模型去实现你的系统。

         不少做业都不是天然并行和独立的,对于这种类型的系统,使用流水线并发模型可以更好的发挥它的优点,并且比并行工做者模型更有优点。

相关文章
相关标签/搜索