并行工作者
委派者将传入的作业分配给不同的工作者,每个工作者完成整个任务,工作者们并行运作在不同的线程上,甚至可能在不同的CPU上。
优点:
易理解,只需要添加工作者提高并行度。
缺点:
1.竞态会出现死锁以及很多其他共享状态的并发性问题。
2.此外,线程互相等待会丢失部分并行性。
3.共享状态能够被系统中得其他线程修改。所以工作者在每次需要的时候必须重读状态,以确保每次都能访问到最新的副本,不管共享状态是保存在内存中的还是在外部数据库中。工作者无法在内部保存这个状态。
4.并行工作者模式的另一个缺点是,作业执行顺序是不确定的。无法保证哪个作业最先或者最后被执行。作业A可能在作业B之前就被分配工作者了,但是作业B反而有可能在作业A之前执行。
流水线
每个工作者在自己的线程中运行,并且不会和其他工作者共享状态。
通常使用非阻塞的IO来设计使用流水线并发模型的系统。
一旦某个工作者开始一个IO操作的时候(比如读取文件或从网络连接中读取数据),这个工作者不会一直等待IO操作的结束。IO操作速度很慢,所以等待IO操作结束很浪费CPU时间。此时CPU可以做一些其他事情。当IO操作完成的时候,IO操作的结果(比如读出的数据或者数据写完的状态)被传递给下一个工作者。
有了非阻塞IO,就可以使用IO操作确定工作者之间的边界。工作者会尽可能多运行直到遇到并启动一个IO操作。然后交出作业的控制权。当IO操作完成的时候,在流水线上的下一个工作者继续进行操作,直到它也遇到并启动一个IO操作。
同时,可能有多个不同的虚拟流水线同时运行。
Actors 和 Channels
在Actor模型中每个工作者被称为actor。Actor之间可以直接异步地发送和处理消息。
而在Channel模型中,工作者之间不直接进行通信。它们在不同的通道中发布自己的消息。其他工作者们可以在这些通道上监听消息,发送者无需知道谁在监听。
一个工作者无需知道谁在后面的流水线上处理作业。只需知道作业(或消息等)需要转发给哪个通道。通道上的监听者可以随意订阅或者取消订阅,并不会影响向这个通道发送消息的工作者。这使得工作者之间具有松散的耦合。
优点:
1.工作者之间无需共享状态,也就无需考虑所有因并发访问共享对象而产生的并发性问题。
2.没有其他线程可以修改它们的数据,可以在内存中保存它们需要操作的数据,只需在最后将更改写回到外部存储系统。比并行者模型性能更好。
3.在某种程度上是有可能保证作业的顺序。
函数式并行
Java7中的java.util.concurrent包里包含的ForkAndJoinPool能够帮助我们实现类似于函数式并行的一些东西。而Java8中并行streams能够用来帮助我们并行的迭代大型集合。
未完待续。。。。。。