Terracotta in Action (2)

2.  Terracotta Eclipse Plugin

    开发基于Terracotta的应用程序的最便捷的方法就是使用TerracottaEclipse Plugin。http://www.terracotta.org/web/display/docs/Eclipse+Plugin+Guide上有详细的安装说明。安装完毕后,通过Terracotta->Add Terracotta Nature可以给已有的工程增加Terracotta Nature。此外也可以通过File->New->Project->Java->Terracotta Projects->Terracotta DSO Project创建一个Terracotta工程。Terracotta工程创建完毕后,工程的根目录下会创建tc-config.xml、terracotta目录和一个Boot jar。tc-config.xml包含了所有Terracotta相关的配置信息,例如需要进行字节码加强的类、Lock相关的配置,共享对象的root、分布式方法的配置等。Terracotta目录用于保存Terracotta客户端的日志和统计信息等。Boot jar的作用会在稍后的章节里介绍。接下来通过两个例子介绍一下Terracotta Eclipse Plugin的使用。

2.1  wait/notify 
    设想某个线程A调用了某个对象obj的wait方法后被阻塞,接下来另一个线程B调用了obj的notify方法从而唤醒了线程A。这在单个JVM中是司空见惯的场景了。但是有没有设想过B线程可以在一个不同于线程A所在的JVM中调用obj的notify方法从而唤醒线程A呢?这在Terracotta的世界里也是司空见惯的场景。
    首先建立一个Terracotta工程,然后创建以下两个普通的Java类:

Java代码   收藏代码
  1. package tcinaction;  
  2.   
  3. public class A {  
  4.       
  5.     public static final Object OBJECT = new Object();  
  6.       
  7.     public static void main(String args[]) throws InterruptedException {  
  8.           
  9.         System.out.println("A is waiting on OBJECT...");  
  10.         synchronized(OBJECT) {  
  11.             OBJECT.wait();  
  12.         }  
  13.         System.out.println("A was woken up");  
  14.     }  
  15. }  
  16.   
  17.   
  18. package tcinaction;  
  19.   
  20. public class B {  
  21.       
  22.     public static void main(String args[]) throws InterruptedException {  
  23.           
  24.         System.out.println("B is calling A.OBJECT.notify()...");  
  25.         synchronized(A.OBJECT) {  
  26.             A.OBJECT.notify();  
  27.         }  
  28.     }  
  29. }  
 

    然后在Package Explorer中选中A,单击右键选中Terracotta->Module A.java->Instrumented,也就是令Terracotta对A类进行字节码加强。对B类也执行同样操作。接下来在A类的OBJECT静态成员变量上单击右键,选中Terracotta->Field OBJECT->Shared root,这样A类的OBJECT就成了在Terracotta中共享的对象。再接下来在A类的main方法上单击右键,选中Terracotta->Method main->Autolock,在弹出的Specify Autolock Attributes对话框中选中Write。对B类的main方法也执行相同的操作。经过了以上操作之后,tc-config.xml的内容如下:

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <con:tc-config xmlns:con="http://www.terracotta.org/config">  
  3.   <servers>  
  4.     <server host="%i" name="localhost">  
  5.       <dso-port>9510</dso-port>  
  6.       <jmx-port>9520</jmx-port>  
  7.       <data>terracotta/server-data</data>  
  8.       <logs>terracotta/server-logs</logs>  
  9.       <statistics>terracotta/cluster-statistics</statistics>  
  10.     </server>  
  11.   </servers>  
  12.   <clients>  
  13.     <logs>terracotta/client-logs</logs>  
  14.     <statistics>terracotta/client-statistics/%D</statistics>  
  15.   </clients>  
  16.   <application>  
  17.     <dso>  
  18.       <instrumented-classes>  
  19.         <include>  
  20.           <class-expression>tcinaction.A</class-expression>  
  21.         </include>  
  22.         <include>  
  23.           <class-expression>tcinaction.B</class-expression>  
  24.         </include>  
  25.       </instrumented-classes>  
  26.       <roots>  
  27.         <root>  
  28.           <field-name>tcinaction.A.OBJECT</field-name>  
  29.         </root>  
  30.       </roots>  
  31.       <locks>  
  32.         <autolock auto-synchronized="false">  
  33.           <method-expression>void tcinaction.B.main(java.lang.String[])</method-expression>  
  34.           <lock-level>write</lock-level>  
  35.         </autolock>  
  36.         <autolock auto-synchronized="false">  
  37.           <method-expression>void tcinaction.A.main(java.lang.String[])</method-expression>  
  38.           <lock-level>write</lock-level>  
  39.         </autolock>  
  40.       </locks>  
  41.     </dso>  
  42.   </application>  
  43. </con:tc-config>  

 

    最后我们来验证一下程序的运行结果。首先选中A类,单击右键Run As->Terracotta DSO Application。此时首先会启动Terracotta server,然后会启动另外一个JVM,运行A类的main方法。输出如下:
    A is waiting on OBJECT...
    接下来选中B类,单击右键Run As->Terracotta DSO Application。此时会再启动一个JVM,执行B类的main方法,相关控制台的输出如下:
    B is calling A.OBJECT.notify()...
    回到A的控制台,发现其主线程已被唤醒并执行完毕,输出如下:
    A is waiting on OBJECT...
    A was woken up

2.2  Simple Messaging 
    在这个例子中介绍一个通过LinkedBlockingQueue在不同JVM中传递数据的方法。首先创建以下两个类:

Java代码   收藏代码
  1. package tcinaction;  
  2.   
  3. import java.util.concurrent.LinkedBlockingQueue;  
  4.   
  5. public class MessageProducer {  
  6.       
  7.     public static final LinkedBlockingQueue<String> PIPE = new LinkedBlockingQueue<String>();  
  8.       
  9.     public static void main(String args[]) throws InterruptedException {  
  10.         for(int i = 0; i < 100; i++) {  
  11.             PIPE.offer("message-" + i);  
  12.             Thread.sleep(1000);  
  13.         }  
  14.     }  
  15. }  
  16.   
  17.   
  18. package tcinaction;  
  19.   
  20. public class MessageConsumer {  
  21.       
  22.     public static void main(String args[]) throws InterruptedException {  
  23.           
  24.         while(true) {  
  25.             String message = MessageProducer.PIPE.take();  
  26.             System.out.println(message);  
  27.         }  
  28.     }  
  29. }  
 

    然后将MessageProducer 和 MessageConsumer配置为instrumented;各自的main方法配置为Autolock(Write);MessageProducer的PIPE静态成员变量配置为Shared root。此时tc-config.xml的内容如下:

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <con:tc-config xmlns:con="http://www.terracotta.org/config">  
  3.   <servers>  
  4.     <server host="%i" name="localhost">  
  5.       <dso-port>9510</dso-port>  
  6.       <jmx-port>9520</jmx-port>  
  7.       <data>terracotta/server-data</data>  
  8.       <logs>terracotta/server-logs</logs>  
  9.       <statistics>terracotta/cluster-statistics</statistics>  
  10.     </server>  
  11.   </servers>  
  12.   <clients>  
  13.     <logs>terracotta/client-logs</logs>  
  14.     <statistics>terracotta/client-statistics/%D</statistics>  
  15.   </clients>  
  16.   <application>  
  17.     <dso>  
  18.       <instrumented-classes>  
  19.         <include>  
  20.           <class-expression>tcinaction.MessageProducer</class-expression>  
  21.         </include>  
  22.         <include>  
  23.           <class-expression>tcinaction.MessageConsumer</class-expression>  
  24.         </include>  
  25.       </instrumented-classes>  
  26.       <locks>  
  27.         <autolock auto-synchronized="false">  
  28.           <method-expression>void tcinaction.MessageConsumer.main(java.lang.String[])</method-expression>  
  29.           <lock-level>write</lock-level>  
  30.         </autolock>  
  31.         <autolock auto-synchronized="false">  
  32.           <method-expression>void tcinaction.MessageProducer.main(java.lang.String[])</method-expression>  
  33.           <lock-level>write</lock-level>  
  34.         </autolock>  
  35.       </locks>  
  36.       <roots>  
  37.         <root>  
  38.           <field-name>tcinaction.MessageProducer.PIPE</field-name>  
  39.         </root>  
  40.       </roots>  
  41.     </dso>  
  42.   </application>  
  43. </con:tc-config>  

 

    最后我们来验证一下程序的运行结果。首先启动MessageConsumer,单击右键Run As->Terracotta DSO Application。然后启动MessageProducer。MessageConsumer的控制台上会显示出接收到的消息:
    message-0
    message-1
    message-2

你可能感兴趣的:(Terracotta in Action (2))