Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Java Programming II Annotations and Reflection Java Threads Java Programming II 1 Contents Annotations Annotating Elements Restricting Annotation Applicability Retention Policies The Class Class Examples Reflection Annotation Queries The Modifier Class The Member classes Java Programming II 2 Annotations The source code for our program is usually accompanied by copious amounts of informal documentation that typically is contained within comments in the source code Many organizations have a standard preamble: copyright information, the programmers name, the date the class was created, etc. Other comments by external tools: version control in a source code management system, or deployment descriptors on how a class should be managed by an application server. Comments based annotation A better way to document the many annotations: to annotate the program elements directly using annotation types Another motivation: many APIs require a fair amount of boilerplate code. (For example, in order to write a JAX-RPC web service, you must provide a paired interface and implementation. ) This boilerplate could be generated automatically by a tool if the program were “decorated” with annotations indicating which methods were remotely accessible. Java Programming II 3 Annotations Provide data about a program that is not part of the program itself. Using annotation type to describe the form of the annotations. Uses of Annotation Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings. Compiler-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth. Runtime processing — Some annotations are available to be examined at runtime. Java Programming II 4 Annotations Documentation Annotation Type Using Annotation Using Comments /*-----------------------------Created: Jan 31 2005 Created By: James Gosling Last Modified: Feb 9 2005 Last Modified By: Ken Arnold Revision: 3 ---------------------------------*/ public class Foo { // ….. } How to use Annotation 1. Define Annotation Type 2. Add Annotation using the type @interface ClassInfo { String created(); String createdBy(); String lastModified(); String lastModifiedBy(); int revision(); } @ClassInfo( created = “Jan 31 2005”, createdBy = “James Gosling”, lastModified =“Feb 9 2005”, lastModifiedBy =“Ken Arnold”, revision =3 ) public class Foo { // class definition… Annotation for the } class Foo Java Programming II 5 Annotation Types Constraint rules of the methods declared in an annotation type (elements of annotation type) The type of the element can only be a primitive type, String , enum, another annotation type, Class, or an array of the preceding types. Cannot declare any parameters. Cannot have a throws clause. Cannot define a type parameter, i.e cannot be a generic method. @interface Revision { int major() default 1; int minor() default 0; } @interface ClassInfo { String created(); String createdBy(); String lastModified(); String lastModifiedBy(); Revision revision(); } Initialization expression @ClassInfo ( created = “Jan 31 2005”, createdBy = “James Gosling”, lastModified = “Feb 9 2005”, lastModifiedBy = “Ken Arnold”, revision = @Revision(major=3) ) public class Foo { // … - Marker annotation: annotation type } which has zero elements (ex) public @interface Preliminary { } Java Programming II 6 Annotation Used by Complier @Deprecated—the @Deprecated annotation indicates that the marked element is deprecated and should no longer be used. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag. // Javadoc comment follows /** * @deprecated * explanation of why it was deprecated */ @Deprecated static void deprecatedMethod() { } } @Override—the @Override annotation informs the compiler that the element is meant to override an element declared in a superclass (overriding methods will be discussed in the the lesson titled "Interfaces and Inheritance"). @SuppressWarnings—the @SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate . In the example of the right site, a deprecated method is used and the compiler would normally generate a warning. In this case, however, the annotation causes the warning to be suppressed. @SuppressWarnings(deprecation) void useDeprecatedMethod() { objectOne.deprecatedMethod(); // deprecation warning suppressed } } Java Programming II 7 Annotating Elements and Restricting Annotation Applicability Marker annotation or all its elements have default values @Deprecated public void badMethod() {/* … */} (an empty list of initializers) @Deprecated() public void badMethod() {/* … */} Array initializer expression @interface BugsFixed { String[] bugIds(); } @BugsFixed(bugIDs = {“1234”, “4567”}) or @BugsFixed(bugIDs = “4567”) When has only a single element (naming of the element is value), it allows for additional shorthand: @inteface BugsFixed { String[] value(); } @BugsFixed({“1234”,”4567”}) @BugsFixed(“4567”) Java Programming II 8 Retention Policies Annotation can serve many different purposes and may be intended for different readers (programmers, or a development tool, compiler, some tool that may need to extract the annotations from a binary representation of a class, and to be inspected at runtime) The Target annotation type Enum constant of ElementType : Represents the different kinds of program elements to which annotations can be applied. ANNOTATION_TYPE : Annotation type declaration CONSTRUCTOR : Constructor declaration FIELD : Field declaration (includes enum constants) LOCAL_VARIABLE : Local variable declaration METHOD : Method declaration PACKAGE : Package declaration PARAMETER : Parameter declaration TYPE : Class, interface (including annotation type), or enum declaration Example @Target (ElementType.TYPE) @interface ClassInfo { String created(); String createdBy(); This will be String lastModified(); applied to type String lastModifiedBy(); declaration Revision revision(); } Java Programming II 9 Retention Policies Three Retention Policies Can be applied when the annotation can be accessed. (Used by @Retention type, Defined by the RetentionPolicy enum) SOURCE: Annotations exist only in the source file CLASS: preserved in the binary representation of the class, but not available at run time RUNTIME: must be available at runtime via the reflection mechanism Example @Retention(RetentionPolicy.RUNTIME) Java Programming II 10 The “Class” class The Class class defines these methods: getName – returns the (class) name getFields – returns all the public fields getMethods – returns all the public methods getPackage – returns the class’ package Java Programming II getSuperclass – returns the class’ superclass getConstructors – returns all the public constructors static Class<?> forName(String className) - returns Class object Annotation[] getAnnotations() - returns all annotations present on this element. 11 Working with Annotations (I) A simple annotation-based test framework “RunTests.java” import java.lang.reflect.*; “Foo.java” import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface Test { } public class RunTests { public static void main(String[] args) throws Exception { int passed = 0, failed = 0; for (Method m : Class.forName(args[0]).getMethods()) { Add “Test” public class Foo { if (m.isAnnotationPresent(Test.class)) { Annotation @Test public static void m1() { } try { public static void m2() { } m.invoke(null); @Test public static void m3() { passed++; throw new RuntimeException("Boom"); } catch (Throwable ex) { } System.out.printf("Test %s failed: %s %n", public static void m4() { } m, ex.getCause()); @Test public static void m5() { } failed++; public static void m6() { } } @Test public static void m7() { } throw new RuntimeException("Crash"); } } System.out.printf("Passed: %d, Failed %d%n", public static void m8() { } passed, failed); } } } Run: % java RunTests Foo Java Programming II 12 Working with Annotations (II) BugsFixedExample: Using Class and getAnnotation method of the “ClassInfo” class “MyFoo.java” import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface BugsFixed { String[] value(); } @BugsFixed( {"1234", "5678"} ) public class MyFoo { } “BugsFixedExample.java” public class BugsFixedExample { public static void main(String[] args) { Class<MyFoo> cls = MyFoo.class; BugsFixed bugsFixed = (BugsFixed) cls.getAnnotation(BugsFixed.class); System.out.println(bugsFixed); String[] bugIds = bugsFixed.value(); for (String id : bugIds) System.out.println(id); } } Run: % java BugsFixedExample Java Programming II 13 Documentation Comments A Simple Example /** * An <code>Attr</code> object defines an attribute as a * name/value pair, where the name is a <code>String</code> * and the value an arbitray <code>Object</code>. * * @version 1.1 * @author Plago * @since 1.0 */ public class Attr { /** The attribute name. */ private final String name; /** The attribute value. */ private Object value = null; /** Returns this attribute's name. */ public String getName() { return name; } /** Returns this attribute's value. */ public Object getValue() { return value; } /** * Sets the value of this attribute. Changes the * value returned by calls to {@link #getValue}. * @param newValue The new value for the attribute. * @return The Original value. * @see #getValue() */ public Object setValue(Object newValue) { Object oldVal = value; value = newValue; return oldVal; } /** * Crates a new attribute with the given name and an * initial value of <code>null</code>. * @see Attr#Attr(String,Object) */ public Attr(String name) { this.name = name; } /** * Creates a new attribute with the given name and * inital value. * @see Attr#Attr(String) */ public Attr(String name, Object value) { this.name = name; this.value = value; } /** * Returns a string of the form <code>name=value</code>. */ public String toString() { return name + "='" + value + "'"; } } Run: % javadoc Attr.java Java Programming II 14 Reflection The reflection is to examine a type in detail. The reflection package : java.lang.reflect Reflection starts with a Class object A simple example of a “type browser”. Argument: import java.lang.reflect.*; import static java.lang.System.out; import static java.lang.System.err; public class SimpleClassDesc { public static void main(String[] args) { Class type = null; try { type = Class.forName(args[0]); } catch(ClassNotFoundException e) { err.println(e); return; } Attr.class out.print("class " + type.getSimpleName()); Class superclass = type.getSuperclass(); if (superclass != null) out.println(" extends " + superclass.getCanonicalName()); else out.println(); Run: % java SimpleClassDesc Attr Result: class Attr extends java.lang.Object public java.lang.String Attr.getName() public java.lang.String Attr.toString() public java.lang.Object Attr.getValue() public java.lang.Object Attr.setValue(java.lang.Object) Method[] methods = type.getDeclaredMethods(); for (Method m : methods) if (Modifier.isPublic(m.getModifiers())) out.println(" " + m); } } The source code is at the /home/course/java2/code/AnnotationReflection/ Java Programming II 15 The Introspection Hierarchy Type ParameterizedType GenericArrayType TypeVariable<D> AnnotatedElement WildcardType AccessibleObject GenericDeclaration Member Class Constructor Method Java Programming II Field Package 16 Type Tokens Type Token Each Class object for a reference type is of a parameterized type corresponding to the class it represents. (Ex: the type of String.class is Class<String>) A parameterized Class type is known as the type token for a given class The easiest way to obtain a type token is to use a class literal. class literal import java.util.*; public class TypeTokenTest { public static void main(String[] args) { Class<String> c1 = String.class; System.out.println("Result1 = " + c1.getClass()); String str = "Hello"; // Class<String> c2 = str.getClass(); // error! Class<? extends String> c2 = str.getClass(); System.out.println("Result2 = " + c2); try { Class<?> c3 = Class.forName("java.lang.String"); //valid Class<? Extends String> c3 = Class.forName("java.lang.String"); //invalid System.out.println("Result3 = " + c3); } catch(ClassNotFoundException e) { System.err.println(e); return; } Exact type token How about this? } } Class<? extends String> c3 = Class.forName("java.lang.String").asSubclass(String.class); Java Programming II 17 Class Inspection import java.lang.reflect.*; public class TypeDesc { public static void main(String[] args) { TypeDesc desc = new TypeDesc(); for (String name : args) { try { Class<?> startClass = Class.forName(name); desc.printType(startClass, 0, basic); } catch (ClassNotFoundException e) { System.err.println(e); // report the error } } } // by default print on standard output private java.io.PrintStream out = System.out; // used in printType(U) for labeling type names private static String[] basic = {"class", "interface", "enum", "annotation"}, supercl = {"extends", "implements"}, iFace = {null, "extends"}; private void printType( Type type, int depth, String[] labels) { if (type == null) // stop recursion -- no supertype return; // turn the Type into a Class object Class<?> cls = null; if (type instanceof Class<?>) { cls = (Class<?>) type; } else if (type instanceof ParameterizedType) { cls = (Class<?>) ((ParameterizedType)type).getRawType(); } else throw new Error("Unexpected non-class type"); Get type token // print this type for (int i = 0; i < depth; i++) out.print(" "); int kind = cls.isAnnotation() ? 3 : cls.isEnum() ? 2 : cls.isInterface() ? 1 : 0 ; out.print(labels[kind] + " "); out.print(cls.getCanonicalName()); // print generic type parameters if present TypeVariable<?>[] params = cls.getTypeParameters(); if (params.length > 0) { out.print('<'); for(TypeVariable<?> param : params) { out.print(param.getName()); out.print(", "); } out.println("\b\b>"); } else out.println(); // print out all interfaces this class implements Type[] interfaces = cls.getGenericInterfaces(); for (Type iface : interfaces) { printType(iface, depth + 1, cls.isInterface() ? iFace : supercl); } // recurse on the superclass printType(cls.getGenericSuperclass(), depth + 1, supercl); } // end of main } // end of clss The source code is at the /home/course/java2/code/AnnotationReflection/Reflection Java Programming II 18 Class Inspection Run: % java TypeDesc java.util.HashMap Result: class java.util.HashMap<K, V> implements java.util.Map<K, V> implements java.lang.Cloneable implements java.io.Serializable extends java.util.AbstractMap<K, V> implements java.util.Map<K, V> extends java.lang.Object Examining the kind of Class object Ask whether have a toplevel type or a nested type, and if nested, some information about which kind of nested type Find out where a type fits in the type hierachy Apply to a subset of those different kinds. Java Programming II 19 Java Programming II Java Threads Java Programming 20 Contents What is Thread? Creating Threads Using Runnable Sleep, Interrupt, and Join Methods Synchronization Java Programming 21 Contents Synchronized statements wait, notifyAll, and notify Methods A Producer and Consumer Example Thread Scheduling Java Programming 22 Concurrent Programming Two basic units in concurrent programming: Processes and Threads. Java Programming is mostly concerned with threads. A thread is called a sequence of steps executed on at a time. The single threaded programming model is the one most programmers use. The multithreading is called the analogue to having multiple real-world bank tellers. bal = a.getBalance(); bal = b.getBalance(); bal += deposit ; bal += deposit ; a.setBalance(bal); b.setBalance(bal); “a” is a thread object of some bank Java Programming “b” is a thread object of another bank 23 An Overview of Threads What is a Thread? A sequence of execution within a process A Lightweight process – requires fewer resources than processes JVM manages and schedules threads Possible States: (1) new (2) ready (3) running (4) waiting (5) dead Java Programming 24 An Overview of Threads Thread life cycle Dead Sleep,wait,I/O New Ready Running Java Programming Waiting 25 How to Create Threads Creating a Thread Object Thread worker = new Thread(); Two ways Using the Thread Class Using the Runnable interface Using the Thread Class Extend the Thread class Implement the run method public class PingPong extends Thread { private String word; private int delay; public PingPong(String whatToSay, int delayTime) { word = whatToSay; delay = delayTime; } public void run() { try { for(;;) { System.out.print(word + “ “); Thread.sleep(delay); } } catch (InterruptedException e) { return; } } public static void main(String[] args) { new PingPong(“ping”, 33).start(); new PingPong(“PONG”,100).start(); } } Java Programming 26 Using Runnable Using Runnable Interface Create a Thread object to pass object of implementation of the Runnable interface into Thread Constructor. Be useful when used with other application such as GUI or applet.. Implement Runnable Interface Implement the run method Create Thread object public class RunPingPong implements Runnable { private String word; private int delay; public PingPong(String whatToSay, int delayTime) { word = whatToSay; delay = delayTime; } public void run() { try { for(;;) { System.out.print(word + “ “); Thread.sleep(delay); } } catch (InterruptedException e) { return; } } public static void main(String[] args) { Runnable ping = new RunPingPong(“ping”, 33); Runnable pong = new RunPingPong(“PONG”, 100); new Thread(ping).start(); new Thread(pong).start(); } } Java Programming 27 Pausing Execution with Sleep Thread.sleep method causes the current thread to suspend execution for a specified period. Efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system. public class SleepMessages { public static void main(String args[]) throws InterruptedException { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; for (int i = 0; i < importantInfo.length; i++) { //Pause for 4 seconds Thread.sleep(4000); //Print a message System.out.println(importantInfo[i]); } The sleep method can also be used for pacing and waiting for another thread with duties that are understood to have time requirements. Sleep Methods } static void sleep(long millis) } static void sleep(long millis, int nanos) Java Programming It throws the InterruptedException. 28 Join The join method allows one thread to wait for the completion of another. t.join(); causes the current thread to pause execution until t's thread terminates. Overloaded Methods void join() : Waits for this thread to die. void join(long millis) void join(long millis, int nanos) class ThreadM extends Thread { public void run() { try { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("ThreadM"); } catch (InterruptedException ex) { ex.printStackTrace(); } } } } class ThreadN extends Thread { public void run() { try { for (int i = 0; i < 20; i++) { Thread.sleep(2000); System.out.println("ThreadN"); } } catch(InterruptedException ex) { ex.printStackTrace(); } } join() method: } Waits for this thread to die. class JoinDemo1 { public static void main(String args[]) { ThreadM tm = new ThreadM(); tm.start(); ThreadN tn = new ThreadN(); tn.start(); try { tm.join(); tn.join(); System.out.println("Both threads have finished"); } catch (Exception e) { e.printStackTrace(); } } } Java Programming 29 Interrupts An interrupt is an indication to a thread that it should stop what it is doing and do something else. A thread sends an interrupt by invoking the “interrupt()” method on the Thread object for the thread to be interrupted. Supporting Interruption If the thread is frequently invoking methods that throw InterruptedException, it simply returns from the run method after it catches that exception. Tests for the interrupt and exits the thread if one has been received. In more complex applications, to throw an InterruptedException for (int i = 0; i < importantInfo.length; i++) { try { Thread.sleep(4000); } catch (InterruptedException e) { //We've been interrupted: no more messages. return; } System.out.println(importantInfo[i]); } for (int i = 0; i < inputs.length; i++) { heavyCrunch(inputs[i]); if (Thread.interrupted()) { //We've been interrupted: no more crunching. return; } } if (Thread.interrupted()) { throw new InterruptedException(); } Java Programming 30 Example: SimpleThreads.java try { public class SimpleThreads { //Display a message, preceded by the name of the current thread //Pause for 4 seconds static void threadMessage(String message) { Thread.sleep(4000); String threadName = Thread.currentThread().getName(); System.out.format("%s: %s%n", threadName, message); } private static class MessageLoop implements Runnable { String importantInfo[] = { "Mares eat oats", "Does eat oats", }; ThreadMessage(importantInfo[i]); } threadMessage("I wasn't done!"); } } // end of run } // end of public static void main(String args[]) throws InterruptedException { public void run() { "A kid will eat ivy too" //Print a message } catch (InterruptedException e) { When this thread receives an interrupt, it happens. "Little lambs eat ivy", for (int i = 0; i < importantInfo.length; i++) { //Delay, in milliseconds before we interrupt MessageLoop //thread (default one hour). long patience = 1000 * 60 * 60; Java Programming 31 Example: SimpleThreads.java //If command line argument present, gives patience in seconds. threadMessage("Waiting for MessageLoop thread to finish"); if (args.length > 0) { //loop until MessageLoop thread exits try { while (t.isAlive()) { patience = Long.parseLong(args[0]) * 1000; } catch (NumberFormatException e) { System.err.println("Argument must be an integer."); System.exit(1); threadMessage("Still waiting..."); //Wait maximum of 1 second for MessageLoop thread to finish. t.join(1000); if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) { } When elapsed time is larger than the patience, it send interrupt to the thread “t”. } threadMessage("Tired of waiting!"); t.interrupt(); //Shouldn't be long now -- wait indefinitely t.join(); threadMessage("Starting MessageLoop thread"); } long startTime = System.currentTimeMillis(); Thread t = new Thread(new MessageLoop()); } t.start(); threadMessage("Finally!"); } } The source code is at the “/home/course/java2/code/Thread/SimpleThreads.java” Java Programming 32 Synchronization Synchronized Methods : protection from interference in a multithreaded environment acquire lock wait to acquire lock synchronized method release lock acquire lock synchronized method release lock If one thread invokes a synchronized method on an object, the lock of that object is first acquired, the method body executed, and then the lock released. Another thread invoking a synchronized method on that same object will block until the lock is released Java Programming 33 Synchronized Methods Example Code public class BankAccount { private long number; // account number private long balance; // current balance (in cents) public BankAccount(long initialDeposit) { When a synchronized balance = initialDeposit; method is invoking, other } synchronized methods in the class cannot be synchronized public long getBalance() { invoked, but nonreturn balance; synchronized methods } can be invoked. private final void setBalance(double amount) { balance = amount; } synchronized public void deposit(double amount) { double bal = getBalance(); bal += amount; setBalance(bal); *Example: Refer to the } “/home/course/java2/code/Thread/TellerTest.java” // … rest of methods } Java Programming 34 Locking Objects with Synchronized Methods thread 1 thread 2 thread 3 run() { obj1.method2(); } run() { obj1.method3(); obj1.method1(); obj2.method1(); } run() { obj2.method3(); obj2.method2(); } 1 4 2 3 OK. 5 6 method1() Not busy obj 1 OK. method2() Not busy synchronized method1() synchronized method2() method3() obj 2 synchronized method1() No! Not while method2() for obj1 is executing synchronized method2() No! Always OK. Not while method1() for obj2 is executing Java Programming method3() Always OK. 35 synchronized Statements Synchronized Statements The synchronized statement enables to execute synchronized code that acquires the lock of any object, not just the current object, or for durations less than the entire invocation of a method. To execute when the lock is obtained. synchronized (expr) { statements } /** make all elements in the array non-negative */ pubic static void abs(int[] values) { synchronized (values) { for (int i=0; i < values.length; i++) { if (values[i] < 0) values[i] = -values[i]; } The array is not changed } during execution by any other } code that is similarly An object whose lock is to be acquired Java Programming synchronized on the values array 36 synchronized Statements A necessity of synchronize statement public void addName(String name) { synchronized(this) { lastName = name; nameCount++; } nameList.add(name); } --- needs to synchronize changes to lastName and nameCount also needs to avoid synchronizing invocations of other objects' methods. In MsLunch, the c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } } Java Programming 37 synchronized Statements Advantages of the synchronized statement Can define a synchronized region of code that is smaller than a method. Allow to synchronize on objects other than this, allowing a number of different synchronization designs to be implemented. A finer granularity of locking. Use for an inner object to synchronize on its enclosing object: You can define separate objects to be used as locks for each such group using synchronized statements class SeparateGroups { private double aVal = 0.0; private double bVal = 1.1; protected final Object lockA = new Object(); protected final Object lockB = new Object(); public double getA() { synchronized(lockA) { return aVal; } } public void setA(double val) { synchronized (lockA) { aVal = val; } } public double getB() { synchronized(lockB) { return bVal; } } public void setB(double val) { synchronized (lockB) { bVal = val; } } public void reset() { synchronized (lockA) { synchronized (lockB) { aVal = bVal = 0.0; } } } } Java Programming 38 Deadlock Deadlock describes a situation where two or more threads are blocked forever, waiting for each other. Alphonse and Gaston are friends, and great believers in courtesy. Bowing Rule: When you bow to a friend, you must remain bowed until your friend has a chance to return the bow. Unfortunately, this rule does not account for the possibility that two friends might bow to each other at the same time. ----public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void bow(Friend bower) { System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName()); bower.bowBack(this); } public synchronized void bowBack(Friend bower) { System.out.format("%s: %s has bowed back to me!%n“, this.name, bower.getName()); } } public static void main(String[] args) { final Friend alphonse = new Friend("Alphonse"); final Friend gaston = new Friend("Gaston"); new Thread(new Runnable() { public void run() { alphonse.bow(gaston); } }).start(); new Thread(new Runnable() { public void run() { gaston.bow(alphonse); } }).start(); } } Java Programming 39 Wait, notifyAll, and notify The wait() method The wait() method allows a thread that is executing a synchronized method or statement block on that object to release the lock and wait for a notification from another thread. The notify() method Standard Pattern of Wait synchronized void doWhenCondition() { while(!condition) wait(); … Do what must be done when the condition is true… } Notification synchronized void changeCondition() { … change some value used in a condition test…. notifyAll(); // or notify() } The notify() method allows a thread that is executing a synchronized method or statement block to notify another thread that is waiting for a lock on this object. Java Programming 40 Wait, notifyAll, and notify Class PrintQueue { private SinglLinkQueue<PrintJob> queue = new SingleLinkQueue<PrintJob>(); public synchronized void add(PrintJob j) { queue.add(j); notifyAll(); // Tell waiters: print job added } public synchronized PrintJob remove() throws InterruptedException { while (queue.size() == 0) wait(); // Wait for a print job return queue.remove(); } } Java Programming 41 Producer & Consumer Example Consumers Producers Java Programming 42 Producer & Consumer Example class Producer extends Thread { Queue queue; Producer(Queue queue) { this.queue = queue; } } public void run() { int i = 0; while(true) { queue.add(i++); } } class Consumer extends Thread { String str; Queue queue; Consumer(String str, Queue queue) { this.str = str; this.queue = queue; } public void run() { while(true) { System.out.println(str + ": " + queue.remove()); } } } class Queue { private final static int SIZE = 10; int array[] = new int[SIZE]; int r = 0; int w = 0; int count = 0; synchronized void add(int i) { while(count == SIZE) { try { wait(); } catch(InterruptedException ie) { ie.printStackTrace(); System.exit(0); } } array[w++] = i; if (w >= SIZE) w = 0; ++count; notifyAll(); } Java Programming 43 Producer & Consumer Example synchronized int remove() { while(count == 0) { try { wait(); } catch(InterruptedException ie) { ie.printStackTrace(); System.exit(0); } } int element = array[r++]; if (r >= SIZE) r = 0; --count; notifyAll(); return element; } } class ProducerConsumers { public static void main(String args[]) { Queue queue = new Queue(); new Producer(queue).start(); new Consumer("ConsumerA", queue).start(); new Consumer("ConsumerB", queue).start(); new Consumer("ConsumerC", queue).start(); } } Java Programming 44 Thread Scheduling Ending Thread Execution The run method returns normally public static void sleep(long millis) public static void sleep(long millis, int nanos) public static void yield() Run: % java Babble false 2 Did DidNot Result: Did Did DidNot class Babble extends Thread { static boolean doYield; static int howOften; private String word; Babble(String whatToSay) { word = whatToSay; } public void run() { for(int i=0; i<howOften; i++) { System.out.println(word); if (doYield) Thread.yield(); // let other threads run } } public static void main(String[] args) { doYield = new Boolean(args[0]).booleanValue(); howOften = Integer.parseInt(args[1]); // create a thread for each world for (int i=2; i < args.length; i++) new Babble(args[i]).start(); } } DidNot Java Programming 45