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
- package demo;
- import java.util.concurrent.CyclicBarrier;
- public class PodRacer {
- public final static int COUNT = 2;
- private final CyclicBarrier barrier = new CyclicBarrier(COUNT);
- private String name;
- public PodRacer(String name) {
- this.name = name;
- }
- public void ready() {
- System.out.println(name + ": ready");
- }
- public void set() throws Exception {
- /* in Terracotta world, all threads in different VMs will block here */
- barrier.await();
- }
- public void go() throws Exception {
- System.out.println(name + ": go");
- Thread.sleep((int) (Math.random() * 5000) + 10);
- System.out.println(name + ": arrived at " + System.currentTimeMillis());
- }
- public static void main(String[] args) throws Exception {
- PodRacer racer = new PodRacer(System.getProperty("racer.name", "unknown"));
- racer.ready();
- racer.set();
- racer.go();
- }
- }
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
- <?xml version="1.0" encoding="UTF-8"?>
- <con:tc-config xmlns:con="http://www.terracotta.org/config">
- <servers>
- <server host="%i" name="localhost">
- <dso-port>9510</dso-port>
- <jmx-port>9520</jmx-port>
- <data>terracotta/server-data</data>
- <logs>terracotta/server-logs</logs>
- </server>
- </servers>
- <clients>
- <logs>terracotta/client-logs</logs>
- </clients>
- <application>
- <dso>
- <instrumented-classes/>
- <roots>
- <root>
- <field-name>demo.PodRacer.barrier</field-name>
- </root>
- </roots>
- </dso>
- </application>
- </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:
- <?xml version="1.0" encoding="UTF-8"?>
- <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">
- <modelVersion>4.0.0</modelVersion>
- <groupId>PodRacing</groupId>
- <artifactId>PodRacing</artifactId>
- <version>0.0.1</version>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.terracotta.maven.plugins</groupId>
- <artifactId>tc-maven-plugin</artifactId>
- <version>1.0.3</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>bootjar</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <processes>
- <process nodeName="racer1"
- className="demo.PodRacer"
- jvmargs="-Dracer.name=Anakin"/>
- <process nodeName="racer2"
- className="demo.PodRacer"
- jvmargs="-Dracer.name=Sebulba"/>
- </processes>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <pluginRepositories>
- <pluginRepository>
- <releases />
- <snapshots />
- <id>terracotta</id>
- <url>http://download.terracotta.org/maven2</url>
- </pluginRepository>
- </pluginRepositories>
- </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.
相关推荐
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 ...
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 ...
Synchronize方法是Delphi中用于在主线程和工作线程之间进行通信的关键工具,确保对用户界面(UI)的操作是安全的。本文将深入探讨Delphi VCL线程同步以及Synchronize方法的工作原理、使用场景和最佳实践。 ### 1. ...
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
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 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 ...
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...
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.
simple configure file to synchronize the connection between two computers (using vnc)
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 ...
- **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 ...
○ 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 是一个针对Notepad++文本编辑器的FTP同步插件,主要用于帮助用户实现本地代码与远程服务器之间的文件同步。Notepad++是一款非常流行的开源文本编辑器,尤其受到程序员和Web开发者的喜爱...
Synchronize It!还有其他特点如下: 1.可以自订许多的项目,包括过滤器、专案、颜色等等。 2.可以进行多种同步任务独立保存和点用,也可组合多个任务一次同步搞定。 3.支持压缩文件的同步。 4.内建二进位文件的比较...
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
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中的`synchronized`关键字是用于实现线程同步的关键机制,主要目的是解决多线程环境下的数据安全问题。当多个线程访问共享资源时,如果没有适当的同步控制,可能会导致数据不一致或者竞态条件等问题。...
以下是关于"CALL RFC synchronize and asychronize Examples"的详细解释。 **同步调用 (Synchronize Call)** 同步调用是立即执行并等待结果返回的方式。在提供的示例`SAPBC415_RFCSYNC_S1`中,我们看到如何通过`...
Node安装以及部署 去官网下载最新版本,分两种一种是源码,一种是编译后的文件。... 以linux Windows为例 Linux 下安装:(方法一) 1.1把下载的tar.gz压缩包文件解压 1.2解压命令: tar -zxvf (压缩包的名字....