ConcurrentShuttleLaunchAnimation.java |
package lectures.animation.threads_commands; import util.annotations.WebDocuments; import lectures.animation.threads_commands.extra.SingleShuttleAnimation; import lectures.composite.objects_shapes.PlottedShuttle; import lectures.mvc.properties.AnObservablePlottedShuttle; import bus.uigen.OEFrame; import bus.uigen.ObjectEditor; /* * You see the nature of threads in three stages. * First, you see visually, in animating user-interfaces, * the consequence of having multiple threads. * * Second, you see threads more directly, through console prints and * the debugger, the existence of threads. * * Finally, you see them most closely, through new kinds of object that * result in the threads being created. * * Study the code in this class, and follow the instructions at the end. */ @WebDocuments({"Lectures/AnimationThreadsCommands.pptx", "Lectures/AnimationThreadsCommands.pdf", "Videos/AnimationThreadsCommands.avi"}) public class ConcurrentShuttleLaunchAnimation extends SingleShuttleAnimation { static int threadNumber = 0; protected final static String SHUTTLE_THREAD_NAME = "Shuttle Animation"; protected final static int START_FRAME_X = 50; protected final static int START_FRAME_Y = 50; protected final static int SHUTTLE2_X = 100; protected final static int SHUTTLE2_Y = 50; protected static int shuttleNumber = 0; protected static PlottedShuttle shuttle1; protected static PlottedShuttle shuttle2; protected static ShuttleAnimator shuttleAnimator1; protected static ShuttleAnimator shuttleAnimator2; protected static void printAllThreads() { System.out.println ("Current threads:" + Thread.getAllStackTraces().keySet()); } public static void concurrentDemoShuttleAnimation(ShuttleAnimator aShuttleAnimator, PlottedShuttle aShuttle) { /* Comment this out and uncomment the following line when asked */ Thread aThread = new Thread( new AShuttleAnimationCommand( aShuttleAnimator, aShuttle, ANIMATION_STEP, ANIMATION_PAUSE_TIME)); // Thread thread = new Thread(); threadNumber++; aThread.setName(SHUTTLE_THREAD_NAME + " " + threadNumber); /* * Comment this out when asked: */ aThread.start(); System.out.println ("Thread:" + Thread.currentThread() + " has started " + aThread); } public static void serialShuttleAnimation() { serialShuttleAnimation(shuttleAnimator1, shuttle1); serialShuttleAnimation(shuttleAnimator2, shuttle2); } public static void concurrentShuttleAnimation() { concurrentDemoShuttleAnimation(shuttleAnimator1, shuttle1); concurrentDemoShuttleAnimation(shuttleAnimator2, shuttle2); } public static void main(String[] args) { shuttle1 = new AnObservablePlottedShuttle(SHUTTLE1_X, SHUTTLE1_Y); shuttle2 = new AnObservablePlottedShuttle(SHUTTLE2_X, SHUTTLE2_Y); displayShuttleFrame(shuttle1); displayShuttleFrame(shuttle2); shuttleAnimator1 = new AShuttleAnimator(); shuttleAnimator2 = new AShuttleAnimator(); // you will need to switch between the two calls serialShuttleAnimation(); // concurrentShuttleAnimation(); System.out.println ("Main terminates"); } /* * SERIAL VS CONCURRENT ANIMATIONS * * Run the program and observe the animations in the object editor user interfaces. * * Now uncomment the call to concurrentShuttleAnimation in main and comment out the * call to serialShuttleAnimation. * * Observe the animations again. * * (T/F) serialShuttleAnimation starts animating shuttle2 after finishing animating * shuttle1. * * (T/F) serialShuttleAnimation ensures that the two shuttles do not climb up at the same * time. * * (T/F) concurrentShuttleAnimation starts animating shuttle2 after finishing * animating shuttle1. * * (T/F) concurrentShuttleAnimation ensures that the two shuttles do not climb up at the same * time. * */ /* * THREAD OBJECTS * * We will go through the same process again, but this time look at the console * output in addition to the OE display. * * The idea is to understand the nature of Thread objects, where Thread is * a predefined Java class. * * The program displays these objects using strings of the form: * Thread[<Thread Name>} * where <Thread Name> is a name given to the Thread object. * * In this program, we give each Thread object a different name. * * * Run main again and observe console output and see how many different Thread * objects are printed out. * * Switch back to serialShuttleAnimation and run main again and observe console * output and see how many different Thread objects are printed out. * * When serialShuttleAnimation runs, the number of thread objects printed is: * 0 * 1 * 2 * 3 * When concurrentShuttleAnimation runs, the number of thread objects printed is: * 0 * 1 * 2 * 3 * * To get further under the hood, let us try and understand where these objects * are being printed. * * Go to the AShuttleAnimator class and answer the questions there. You will need to * switch between serial and concurrent execution in this class. */ /* * COMMAND OBJECTS * * You saw in AShuttleAnimator something about the behavior of running threads. * Let us try to understand how threads are started. * * We saw that each runnable thread is associated with a Thread object. * We also saw that other than the main thread, all threads have Thread.run() * at the base of the stack. * If different threads do different things, then somehow different Thread.run() calls * should call different methods. * * Thread.run() does not take parameters. So, this means that when a Thread object is * constructed, we must tell the constructor which method to call and what the parameters * of the method should be. * * These two pieces of information are encapsulated in a command object, which * is passed to the thread constructor. * * concurrentDemoShuttleAnimation shows the use of Thread objects. * * It creates a thread and then starts it. * * Look at the output produced by it. * * Thread[Shuttle Animation 2] is started by: * (a) Thread[Shuttle Animation 1] * (b) Thread[main] * * * Comment out Thread.start(), switch to concurrent animation, and observe what * happens. * * (T/F) If a thread is not started, then its run method is not called. * * Uncomment Thread.start() and switch to the alternate commented out Thread * instantiation and observe what happens. * * (T/F) If the command object is not passed to the Thread constructor, then * the animation does not start. * * Go to AShuttleAnimationCommand */ /* * THREAD AND ANIMATION DESIGN PATTERN * We see here a design pattern for using threads to animate objects that has * the following components: * * Animated object - the object being animated. In this case it is an instance of * AnObservablePlottedShuttle. * * The animating object - the object implementing the animation. In this case, * it is an instance of AShuttleAnimator. * * Command object - this object wraps a call to the animating object so that it * can be placed inside a separate thread. The command object is what starts the * animation (here, it is AShuttleAnimationCommand). * * Thread object - this object takes a command object and allows the animation to * proceed in a separate, concurrent thread. This is the Java Thread object. * * * Based on this design pattern answer the following questions: * * (T/F) The class of the animated object must be changed to change the animation. * * (T/F) A Thread object knows how an object is animated. * * (T/F) A Thread object interacts with a command object directly. * * (T/F) A Thread object interacts with an animating object directly. * * (T/F) A command object interacts with an animated object directly. * * (T/F) A command object interacts with an animating object directly. * * (T/F) The class of a command object is a subclass of the Thread class. * * (T/F) It is possible to create two different threads and command objects that * animate the same object simultaneously. * (You do not see the answer directly in the praxis so have to deduce it from what you have learned) * * (T/F) A command object can be used only to start threads. * (You do not see the answer directly in the praxis so have to deduce it from what you have learned) */ }