`
wbj0110
  • 浏览: 1598777 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

How to synchronize threads across multiple JVMs

阅读更多

Sometimes, you want to start the job in multiple JVMs only when all the VM has started. This scenario often comes up with multiplayer games. Let's take a pod racing game for example. The players need to start at the same time and each game server handles 1 player (for simplicity's sake)

Starting from Java 5, there's a CyclicBarrier to synchronize threads and is a perfect tool for this. However, it only handles threads in 1 VM. D'oh! Here's where Terracotta comes in. If you make that CyclicBarrier a shared object, Terracotta will handle the clustering for you, transparently (no API). All of a sudden, your CyclicBarrier object will be seen across all the VMs participated in the game. 

Here's an example of how to do it. First, let's take a look at the PodRacer class

  1. package demo;  
  2.   
  3. import java.util.concurrent.CyclicBarrier;  
  4.   
  5. public class PodRacer {  
  6.   public final static int     COUNT   = 2;  
  7.   private final CyclicBarrier barrier = new CyclicBarrier(COUNT);  
  8.   private String              name;  
  9.   
  10.   public PodRacer(String name) {  
  11.     this.name = name;  
  12.   }  
  13.   
  14.   public void ready() {  
  15.     System.out.println(name + ": ready");  
  16.   }  
  17.   
  18.   public void set() throws Exception {  
  19.     /* in Terracotta world, all threads in different VMs will block here */  
  20.     barrier.await();  
  21.   }  
  22.   
  23.   public void go() throws Exception {  
  24.     System.out.println(name + ": go");  
  25.     Thread.sleep((int) (Math.random() * 5000) + 10);  
  26.     System.out.println(name + ": arrived at " + System.currentTimeMillis());  
  27.   }  
  28.   
  29.   public static void main(String[] args) throws Exception {  
  30.     PodRacer racer = new PodRacer(System.getProperty("racer.name""unknown"));  
  31.     racer.ready();  
  32.     racer.set();  
  33.     racer.go();  
  34.   }  
  35. }  



Notice I hardcoded number of racers here to 2 but it can be made dynamic. If you run this class just like a normal Java program, it will block at racer.set() call because there's only 1 thread arriving at the barrier whereas it requires 2 for the barrier to be lifted. And if you don't use Terracotta underneath, it doesn't matter how many VMs you start, it will just block there.

Next, I'll add Terracotta into the mix and share the barrier object. That can be achieved by marking it in Terracotta configuration file tc-config.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.     </server>  
  10.   </servers>  
  11.   <clients>  
  12.     <logs>terracotta/client-logs</logs>  
  13.   </clients>  
  14.   <application>  
  15.     <dso>  
  16.       <instrumented-classes/>  
  17.       <roots>  
  18.         <root>  
  19.           <field-name>demo.PodRacer.barrier</field-name>  
  20.         </root>  
  21.       </roots>  
  22.     </dso>  
  23.   </application>  
  24. </con:tc-config>  



And that's it. When I start 2 JVMs running PodRacer class with Terracotta, I will efficiently have 2 threads calling racer.set() on the shared barrier

To make it even easier to try out with Terracotta, there's a Maven 2 plugin that will handle starting up your project with Terracotta enabled. Here's the pom.xml of my project:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  3.   <modelVersion>4.0.0</modelVersion>  
  4.   <groupId>PodRacing</groupId>  
  5.   <artifactId>PodRacing</artifactId>  
  6.   <version>0.0.1</version>  
  7.   <build>  
  8.     <plugins>  
  9.       <plugin>  
  10.         <artifactId>maven-compiler-plugin</artifactId>  
  11.         <configuration>  
  12.           <source>1.5</source>  
  13.           <target>1.5</target>  
  14.         </configuration>  
  15.       </plugin>  
  16.       <plugin>  
  17.         <groupId>org.terracotta.maven.plugins</groupId>  
  18.         <artifactId>tc-maven-plugin</artifactId>  
  19.         <version>1.0.3</version>  
  20.         <executions>  
  21.           <execution>  
  22.             <phase>package</phase>  
  23.             <goals>  
  24.               <goal>bootjar</goal>  
  25.             </goals>  
  26.           </execution>  
  27.         </executions>  
  28.           
  29.         <configuration>  
  30.           <processes>  
  31.             <process nodeName="racer1"   
  32.                      className="demo.PodRacer"  
  33.                      jvmargs="-Dracer.name=Anakin"/>  
  34.             <process nodeName="racer2"   
  35.                      className="demo.PodRacer"  
  36.                      jvmargs="-Dracer.name=Sebulba"/>  
  37.           </processes>  
  38.             
  39.         </configuration>  
  40.       </plugin>  
  41.     </plugins>  
  42.   </build>  
  43.   <pluginRepositories>  
  44.     <pluginRepository>  
  45.       <releases />  
  46.       <snapshots />  
  47.       <id>terracotta</id>  
  48.       <url>http://download.terracotta.org/maven2</url>  
  49.     </pluginRepository>  
  50.   </pluginRepositories>  
  51. </project>  



See how I defined 2 racers through the process element in the plugin configuration. That will start 2 distinct VMs with Terracotta enabled. The output looks something like this:

[INFO] Starting DSO nodes 
[INFO] Starting node racer1: c:\jdk\jdk1.6.0_02\jre/bin/java.exe -Dcom.tc.l1.modules.repositories=file:/C:/Users/hhuynh/.m2/repository/ -Dtc.nodeName=racer1 -Dtc.numberOfNodes=2 -Dtc.config=d:\work\workspace\projects\PodRacing\tc-config.xml -Dtc.classpath=file:/c:/Users/hhuynh/AppData/Local/Temp/tc-classpath37736.tmp -Dtc.session.classpath=/C:/Users/hhuynh/.m2/repository/org/terracotta/tc-session/2.5.0/tc-session-2.5.0.jar -Dcom.tc.l1.modules.repositories=file:/C:/Users/hhuynh/.m2/repository/ -Xbootclasspath/p:d:\work\workspace\projects\PodRacing\target\dso-boot.jar -Dracer.name=Anakin -cp d:\work\workspace\projects\PodRacing\target\classes; demo.PodRacer
[INFO] Starting node racer2: c:\jdk\jdk1.6.0_02\jre/bin/java.exe -Dcom.tc.l1.modules.repositories=file:/C:/Users/hhuynh/.m2/repository/ -Dtc.nodeName=racer2 -Dtc.numberOfNodes=2 -Dtc.config=d:\work\workspace\projects\PodRacing\tc-config.xml -Dtc.classpath=file:/c:/Users/hhuynh/AppData/Local/Temp/tc-classpath37737.tmp -Dtc.session.classpath=/C:/Users/hhuynh/.m2/repository/org/terracotta/tc-session/2.5.0/tc-session-2.5.0.jar -Dcom.tc.l1.modules.repositories=file:/C:/Users/hhuynh/.m2/repository/ -Xbootclasspath/p:d:\work\workspace\projects\PodRacing\target\dso-boot.jar -Dracer.name=Sebulba -cp d:\work\workspace\projects\PodRacing\target\classes; demo.PodRacer
[INFO] ------------------------------------------------------------------------

[INFO] [racer2] Sebulba: ready
[INFO] [racer1] Anakin: ready
[INFO] [racer1] Anakin: go
[INFO] [racer2] Sebulba: go
[INFO] [racer2] Sebulba: arrived at 1202406914274
[INFO] Finished node racer2
[INFO] [racer1] Anakin: arrived at 1202406915125
[INFO] Finished node racer1



Ouch, Anakin sucked!

Download the Maven project and try it out. Have fun.


分享到:
评论

相关推荐

    Java 7 Concurrency Cookbook

    of how to use the new Java 7 Phaser class to synchronize tasks divided into phases. Chapter 4, Thread Executors will teach the readers to delegate the thread management to executors. They allow ...

    操作系统英文教学课件:Chapter 4 Threads.ppt

    It provides a portable API for developers to create, synchronize, and manage threads across different platforms. In conclusion, understanding threading is essential for developing efficient and ...

    delphi vcl线程同步synchronize

    Synchronize方法是Delphi中用于在主线程和工作线程之间进行通信的关键工具,确保对用户界面(UI)的操作是安全的。本文将深入探讨Delphi VCL线程同步以及Synchronize方法的工作原理、使用场景和最佳实践。 ### 1. ...

    NTP Security(Apress,2016)

    Learn the risks ...Determine the alternatives to NTP, including how to synchronize network clocks in other ways Who This Book Is For: System administrators, network engineers, and security analysts

    Multithreading with C# Cookbook(PACKT,2ed,2016)

    Work with raw threads, synchronize threads, and coordinate their work Develop your own asynchronous API with Task Parallel Library Work effectively with a thread pool Scale up your server ...

    igosyncdocs-iGoSyncDocs-Beta.tar.gz_coming soon_google docs

    iGoSyncDocs is a desktop application(Swing based) that offers an easy way to access and synchronize files to Google Docs across multiple computers. Rember that iGoSyncDocs running under jdk1.6. And ...

    Active Directory Cookbook, 3rd Edition.pdf

    Provides an introduction to Microsoft’s Identity Integration Server (MIIS), a service that can be used to synchronize multiple directories or enforce data integrity within a single or multiple stores...

    怎么样使pda 和计算机中数据库 数据同步

    The main objective of the article is to present how to synchronize the data in the pocket pc database and main database using Pocket PC Emulator and Web Service in Dot Net.

    vnc.rar_Computers_file synchronize

    simple configure file to synchronize the connection between two computers (using vnc)

    Apple Watch App Development(PACKT,2016)

    By the end of this book, you will have a good understanding of how to develop apps for the Apple Watch platform, and synchronize data using iCloud between the wearable and the iOS device. What You ...

    iOS 8 Swift Programming Cookbook Solutions Examples for iOS Apps.pdf

    - **Concept**: CloudKit is a powerful framework that enables developers to store data on Apple's servers and synchronize it across multiple devices. This feature is particularly useful for creating ...

    CS195V Brown - Week 11 - CUDA Part 2 - Slides-计算机科学

    ○ You can synchronize across threadsin a block to ensure r/w is complete Global memory requires you to use multiple kernel invocations (since you don't know when a r/w op is done)Reductions● A ...

    FTP_synchronize_0_9_6_1_dll

    FTP_synchronize_0_9_6_1_dll 是一个针对Notepad++文本编辑器的FTP同步插件,主要用于帮助用户实现本地代码与远程服务器之间的文件同步。Notepad++是一款非常流行的开源文本编辑器,尤其受到程序员和Web开发者的喜爱...

    Synchronize It 3.5文件夹同步器 简体中文界面

    Synchronize It!还有其他特点如下: 1.可以自订许多的项目,包括过滤器、专案、颜色等等。 2.可以进行多种同步任务独立保存和点用,也可组合多个任务一次同步搞定。 3.支持压缩文件的同步。 4.内建二进位文件的比较...

    APS007_Wired-Sync-RTLS-With-The-DW1000_v1.10.pdf

    WIRED SYNCHRONIZATION OF ANCHOR NODES IN A TDOA REAL TIME LOCATION SYSTEM How to synchronize anchor nodes using a wired scheme in an RTLS based on DecaWave’s DW1000 IC

    go系统编程(英文版)

    goroutines, by talking about how you can create goroutines and how you can synchronize them and wait for them to finish before ending a program. Then it talks about channels and pipelines, which help ...

    java synchronize 线程同步

    Java中的`synchronized`关键字是用于实现线程同步的关键机制,主要目的是解决多线程环境下的数据安全问题。当多个线程访问共享资源时,如果没有适当的同步控制,可能会导致数据不一致或者竞态条件等问题。...

    CALL RFC synchronize and asychronize Examples

    以下是关于"CALL RFC synchronize and asychronize Examples"的详细解释。 **同步调用 (Synchronize Call)** 同步调用是立即执行并等待结果返回的方式。在提供的示例`SAPBC415_RFCSYNC_S1`中,我们看到如何通过`...

    pm2 部署 node的三种方法示例

    Node安装以及部署 去官网下载最新版本,分两种一种是源码,一种是编译后的文件。... 以linux Windows为例 Linux 下安装:(方法一)  1.1把下载的tar.gz压缩包文件解压  1.2解压命令: tar -zxvf (压缩包的名字....

Global site tag (gtag.js) - Google Analytics