Java线程间通讯概述2014-06-02 infoq Aliaksei Papou 译:吴海这个故事源自一个很简单的想法:创建一个对开发人员友好的、简单轻量的线程间通讯框架,完全不 用锁、同步器、信号量、等待和通知,在Java里开发一个轻量、无锁的线程内通讯框架;并且也没有队列 、消息、事件或任何其他并发专用的术语或工具。只用普通的老式Java接口实现POJO的通讯。它可能跟Akka的类型化actor类似,但作为一个必须超级轻量,并且要针对单台多核计算机进行优化的 新框架,那个可能有点过了。当actor跨越不同JVM实例(在同一台机器上,或分布在网络上的不同机器上)的进程边界时,Akka框 架很善于处理进程间的通讯。但对于那种只需要线程间通讯的小型项目而言,用Akka类型化actor可能有点儿像用牛刀杀鸡,不过类 型化actor仍然是一种理想的实现方式。我花了几天时间,用动态代理,阻塞队列和缓存线程池创建了一个解决方案。图一是这个框架的高层次架构:
图一: 框架的高层次架构SPSC队列是指单一生产者/单一消费者队列。MPSC队列是指多生产者/单一消费者队列。派发线程负责接收Actor线程发送的消息,并把它们派发到对应的SPSC队列中去。接收到消息的Actor线程用其中的数据调用相应的actor实例中的方法。借助其他actor的代理,actor 实例可以将消息发送到MPSC队列中,然后消息会被发送给目标actor线程。我创建了一个简单的例子来测试,就是下面这个打乒乓球的程序:
public interface PlayerA (void pong(long ball); //发完就忘的方法调用 }public interface PlayerB { void ping(PlayerA playerA, long ball); //发完就忘的方法调用 }public class PlayerAImpl implements PlayerA {@Overridepublic void pong(long ball) {}}public class PlayerBImpl implements PlayerB { @Overridepublic void ping(PlayerA playerA, long ball) {playerA.pong(ball);}}public class PingPongExample { public void testPingPong() {// 管理器隐藏了线程间通讯的复杂性// 控制actor代理,actor实现和线程ActorManager manager = new ActorManager();// 在管理器内注册actor实现 manager.registerImpl(PlayerAImpl.class);manager.registerImpl(PlayerBImpl.class);//创建actor代理。代理会将方法调用转换成内部消息。 //会在线程间发给特定的actor实例。PlayerA playerA = manager.createActor(PlayerA.class);PlayerB playerB = manager.createActor(PlayerB.class);for(int i = 0; i < 1000000; i++) { playerB.ping(playerA, i);}}