Main.java
001 /*
002  *
003  * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
004  *
005  */
006 package demo.coordination;
007 
008 import java.text.DateFormat;
009 import java.util.Date;
010 import java.util.concurrent.BrokenBarrierException;
011 import java.util.concurrent.CyclicBarrier;
012 
013 /**
014  * Sample to demonstrate how to use CyclicBarrier to coordinate between JVMs
015  */
016 public class Main {
017   // banner text displayed on startup
018   private static String text0                         = "\n"
019                                                           "JVM Coordination\n"
020                                                           "\n"
021                                                           "This sample application show how to coordinate threads in a multi-VM\n"
022                                                           "environment using the same patterns one would use in a multi-threaded\n"
023                                                           "single-VM environment.\n";
024 
025   // these are the text messages we use to display the state of the application
026   private static String text1                         = "Application started; I expect a total of @TOKEN@ VMs that will be participating.\n"
027                                                           "At this point the application is waiting for the other pariticipants (or VMs) to startup.\n"
028                                                           "When all of the participants are available, it will perform its task and exit.\n\n"
029                                                           "Notice that all the other participants also come into a wait state just like the first VM that\n"
030                                                           "you launched; they will only proceed as soon as the number of VMs that you have launched\n"
031                                                           "matches the number of participants it expects.\n\n"
032                                                           "Waiting for all other VMs to join...\n";
033   private static String text2                         = "I am node: @TOKEN@\n"
034                                                           "The number of VMs that I expect to participate has launched.\n"
035                                                           "I will now perform my task by printing today's date and current time:\n\n"
036                                                           "Here it is:\n@TOKEN@\n\n"
037                                                           "I have completed my task."
038                                                           "I am now waiting for all the other VMs finish their task...\n";
039   private static String text3                         = "All of the participating VMs have completed their task.\n"
040                                                           "I am stopping now.";
041 
042   private int           expectedParticipants;
043   private CyclicBarrier enterBarrier;
044   private CyclicBarrier exitBarrier;
045   private static int    MINIMUM_EXPECTED_PARTICIPANTS = 2;
046 
047   /**
048    * Create an instance, setting the number of VMs expected to participate in
049    * the demo.
050    */
051   public Main(int expectedParticipants) {
052     // enforce minimum number of participants
053     if (expectedParticipants < MINIMUM_EXPECTED_PARTICIPANTS) {
054       expectedParticipants = MINIMUM_EXPECTED_PARTICIPANTS;
055       System.out.println("(You did not pass an argument, I'm assuming "
056           + expectedParticipants + " VMs will be participating)\n");
057     }
058     this.expectedParticipants = expectedParticipants;
059     this.enterBarrier = new CyclicBarrier(expectedParticipants);
060     this.exitBarrier = new CyclicBarrier(expectedParticipants);
061   }
062 
063   /**
064    * Start up multiple threads and wait. Once all the theads have started,
065    * execute some code. When all threads have finished executing the code,
066    * coordinate the shutdown of the participants.
067    */
068   public void run() {
069     try {
070       // wait for all participants before performing tasks
071       System.out.println(text1.replaceFirst("@TOKEN@", Integer
072           .toString(expectedParticipants)));
073       enterBarrier.await();
074 
075       // perform task once all of the expected participants is present
076       String currentDateAndTime = DateFormat.getDateTimeInstance(
077           DateFormat.SHORT, DateFormat.SHORT).format(new Date());
078       System.out.println(text2.replaceFirst("@TOKEN@",
079           this + Integer.toString(expectedParticipants)).replaceFirst(
080           "@TOKEN@", currentDateAndTime));
081 
082       // wait for all participants to complete their task before exiting
083       exitBarrier.await();
084       System.out.println(text3);
085     catch (InterruptedException ie) {
086       throw new RuntimeException(ie);
087     catch (BrokenBarrierException bbe) {
088       throw new RuntimeException(bbe);
089     }
090   }
091 
092   public static final void main(String[] argsthrows Exception {
093     System.out.println(text0);
094 
095     int expectedParticipants = 0;
096     try {
097       expectedParticipants = Integer.parseInt(args[0]);
098     catch (Exception e) {
099     }
100 
101     (new Main(expectedParticipants)).run();
102   }
103 }