在Java中使用协程(Coroutine)

来源:互联网 发布:雨人软件科技有限公司 编辑:程序博客网 时间:2024/04/30 12:51

各种语言在实现Coroutine方式的支持时,多数都采用了Actor Model来实现,Actor Model简单来说就是每个任务就是一个Actor,Actor之间通过消息传递的方式来进行交互,而不采用共享的方式,Actor可以看做是一个轻量级的进程或线程,通常在一台4G内存的机器上,创建几十万个Actor是毫无问题的。

对于Java应用而言,传统方式下为了支持高并发,由于一个线程只能用于处理一个请求,即使是线程中其实有很多IO中断、锁等待也同样如此,因此通常的做法是通过启动很多的线程来支撑高并发,但当线程过多时,就造成了CPU需要消耗不少的时间在线程的切换上,从而出现瓶颈,按照上面对Coroutine的描述,Coroutine的方式理论上而言能够大幅度的提升Java应用所能支撑的并发量。

Kilim是由剑桥的两位博士开发的一个用于在Java中使用Coroutine的框架,Kilim基于Java语法,先来看看Kilim中的关键概念。

l  Task

可以认为Task就是Actor,使用方式和Java Thread基本相同,只是继承的为Task,覆盖的为execute方法,启动也是调用task的start方法。

l  Task的消息发送机制

Kilim中通过Mailbox对象来发送消息,Mailbox的基本原则为可以有多个消息发送者,但只能有一个消息接收者,发送的方式有同步发送、异步发送和阻塞线程方式的同步发送三种,同步发送是指保证一定能将消息放入发送队列中,如当前发送队列已满,则等待到可用为止,阻塞的为当前Task;异步发送则是尝试将消息放入发送队列一次,如失败,则返回false,成功则返回true,不会阻塞Task;阻塞线程方式的同步发送是指阻塞当前线程,并保证将消息发送给接收者,三种方式的使用方法如下:

mailbox.put(messageObject); // 同步发送

mailbox.putnb(messageObject); // 异步发送

mailbox.putb(messageObject); // 阻塞线程方式发送

l  Task的消息接收机制

Kilim中通过Mailbox来接收消息,接收消息的方式有同步接收、异步接收以及阻塞线程方式的同步接收三种,同步接收是指阻塞当前Task,直到接收到消息才返回;异步接收是指立刻返回Mailbox中的消息,有就返回,没有则返回null;阻塞线程方式的同步接收是指阻塞当前线程,直到接收到消息才返回,使用方法如下:

mailbox.get(); // 同步接收,传入long参数表示等待的超时时间,单位为毫秒

mailbox.getnb(); // 异步接收,立刻返回

mailbox.getb(); // 阻塞线程方式接收

 

在实际Java应用中使用Coroutine时,通常会出现以下几种典型的更复杂的使用场景,由于Actor模式本身就是异步的,因此其天然对异步场景支持的就非常好。

在Kilim中要实现Task之间的同步调用非常简单,代码如下:

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class TaskA extends Task{  
  2.          public void execute() throws Pausable,Exception{  
  3.                    Mailbox<Object> result=new Mailbox<Object>();  
  4. Task task=new TaskB(result);  
  5.                    task.start();  
  6.                    Object resultObject=result.get();  
  7.                    System.out.println(resultObject);  
  8. }  
  9. }  
  10. public class TaskB extends Task{  
  11.          private Mailbox<Object> result;  
  12. public TaskB(Mailbox<Object> result){  
  13.                    this.result=result;  
  14. }  
  15. public void execute() throws Pausable,Exception{  
  16.          result.put(“result from TaskB”);  
  17. }  
  18. }  
public class TaskA extends Task{         public void execute() throws Pausable,Exception{                   Mailbox<Object> result=new Mailbox<Object>();Task task=new TaskB(result);                   task.start();                   Object resultObject=result.get();                   System.out.println(resultObject);}}public class TaskB extends Task{         private Mailbox<Object> result;public TaskB(Mailbox<Object> result){                   this.result=result;}public void execute() throws Pausable,Exception{         result.put(“result from TaskB”);}}
Kilim的Mailbox.get并不会阻塞线程,因此这种方式是完全满足需求的。

 

 

 

0 0
原创粉丝点击