Threads ======= 1) What are the differences between processes and threads? 2) How can I instantiate a new thread in Java? public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new Thread(new HelloRunnable())).start(); } } - or - public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new HelloThread()).start(); } } 3) What are the advantages and disadvantages of each approach? 4) What does this program do? 4.1) Why we have to declare that it throws an exception? public class SleepMessages { //Display a message, preceded by the name of the current thread static void threadMessage(String message) { String threadName = Thread.currentThread().getName(); System.out.format("%s: %s%n", threadName, message); } public static void main(String args[]) throws InterruptedException { String importantInfo[] = { "Boi, boi, boi...", "Boi da cara preta,", "Pega este menino...", "Que tem medo de careta." }; for (int i = 0; i < importantInfo.length; i++) { //Pause for 2 seconds Thread.sleep(2000); //Print a message threadMessage(importantInfo[i]); } } } 5) What does this modified version do? 5.1) How is it different from the SleepMessages? public class MessageLoop implements Runnable { //Display a message, preceded by the name of the current thread static void threadMessage(String message) { String threadName = Thread.currentThread().getName(); System.out.format("%s: %s%n", threadName, message); } public void run() { String importantInfo[] = { "Boi, boi, boi...", "Boi da cara preta,", "Pega este menino...", "Que tem medo de careta." }; try { for (int i = 0; i < importantInfo.length; i++) { //Pause for 2 seconds Thread.sleep(2000); //Print a message threadMessage(importantInfo[i]); } } catch (InterruptedException e) { threadMessage("I wasn't done!"); } } public static void main(String args[]) { (new Thread(new MessageLoop())).start(); } } * An instance of Thread has an interrupt() method that can be invoked on that object to stop it. 6) What is the effect of invoking interrupt() on an object? 7) What does this program do? public class SimpleThreads { public static void main(String args[]) throws InterruptedException { //Delay, in milliseconds before we interrupt MessageLoop //thread (default one hour). long patience = 1000 * 60 * 60; //If command line argument present, gives patience in seconds. if (args.length > 0) { patience = Long.parseLong(args[0]) * 1000; } MessageLoop.threadMessage("Starting MessageLoop thread"); long startTime = System.currentTimeMillis(); Thread t = new Thread(new MessageLoop()); t.start(); MessageLoop.threadMessage("Waiting for MessageLoop thread to finish"); //loop until MessageLoop thread exits while (t.isAlive()) { MessageLoop.threadMessage("Still waiting..."); //Wait maximum of 1 second for MessageLoop thread to //finish. t.join(1000); if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) { MessageLoop.threadMessage("Tired of waiting!"); t.interrupt(); //Shouldn't be long now -- wait indefinitely t.join(); } } MessageLoop.threadMessage("Finally!"); } } 8) Which special methods have we seen in this program? run sleep interrupt join 9) what problems might happen if two threads invoke methods on instances of the following class? class Counter { private int c = 0; public void increment() { c++; } public void decrement() { c--; } public int value() { return c; } } * The problem is interleaving: 1. Retrieve the current value of c. 2. Increment the retrieved value by 1. 3. Store the incremented value back in c. * Example: Thread A: Retrieve c. Thread B: Retrieve c. Thread A: Increment retrieved value; result is 1. Thread B: Decrement retrieved value; result is -1. Thread A: Store result in c; c is now 1. Thread B: Store result in c; c is now -1. 10) How to fix this synchronization problem? public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } } 10.1) What is the meaning of the synchronized keyword? 11) We cannot have synchronized constructors. Why they don't make sense? 12) What if an object has two fields that are never used together? Would synchronized be a waste in this case? 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++; } } } * Some operations are atomic. Examples are update of primitive types, except long and double. 13) The program below has a problem. Which problem? 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()); } } static class Bower extends Thread { private Friend bower, bowed; public Bower(Friend bower, Friend bowed) { this.bower = bower; this.bowed = bowed; } public void run() { bower.bow(bowed); } } public static void main(String[] args) { final Friend alphonse = new Friend("Alphonse"); final Friend gaston = new Friend("Gaston"); Bower b1 = new Bower(alphonse, gaston); Bower b2 = new Bower(gaston, alphonse); b1.start(); b2.start(); } } 13.1) What is a deadlock? 14) Two other problems are Starvation and livelock. What is this? 15) What is the problem with the code below? public void guardedJoy() { //Simple loop guard. Wastes processor time. Don't do this! while(!joy) {} System.out.println("Joy has been achieved!"); } 15.1) How to fix it? // Solution 1 public synchronized guardedJoy() { //This guard only loops once for each special event, which may not //be the event we're waiting for. while(!joy) { try { wait(); } catch (InterruptedException e) {} } System.out.println("Joy and efficiency have been achieved!"); } 15.2) Why we did not do anything about the exception? 15.3) How is the notification code? public synchronized notifyJoy() { joy = true; notifyAll(); } 15.4) What is the difference between wait and sleep? 16) What is a producer/consumer pattern? 16.1) How to implement such a thing in Java? public class Drop { //Message sent from producer to consumer. private String message; //True if consumer should wait for producer to send message, false //if producer should wait for consumer to retrieve message. private boolean empty = true; public synchronized String take() { //Wait until message is available. while (empty) { try { wait(); } catch (InterruptedException e) {} } //Toggle status. empty = true; //Notify producer that status has changed. notifyAll(); return message; } public synchronized void put(String message) { //Wait until message has been retrieved. while (!empty) { try { wait(); } catch (InterruptedException e) {} } //Toggle status. empty = false; //Store message. this.message = message; //Notify consumer that status has changed. notifyAll(); } } 16.2) How is the consumer code? import java.util.Random; public class Consumer implements Runnable { private Drop drop; public Consumer(Drop drop) { this.drop = drop; } public void run() { Random random = new Random(); for (String message = drop.take(); ! message.equals("DONE"); message = drop.take()) { System.out.format("MESSAGE RECEIVED: %s%n", message); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) {} } } } 16.3) How is the producer code? import java.util.Random; public class Producer implements Runnable { private Drop drop; public Producer(Drop drop) { this.drop = drop; } public void run() { String importantInfo[] = { "Boi, boi, boi...", "Boi da cara preta...", "Pega este menino,", "Que tem medo de careta" }; Random random = new Random(); for (int i = 0; i < importantInfo.length; i++) { drop.put(importantInfo[i]); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) {} } drop.put("DONE"); } } 16.4) And how is the driver code? public class ProducerConsumerExample { public static void main(String[] args) { Drop drop = new Drop(); (new Thread(new Producer(drop))).start(); (new Thread(new Consumer(drop))).start(); } } 17) How can we avoid data-races? 17.1) One way to avoid data races is using immutable objects. What is this? 17.2) How to make the following class immutable? public class SynchronizedRGB { //Values must be between 0 and 255. private int red; private int green; private int blue; private String name; public SynchronizedRGB(int red, int green, int blue, String name) {...} public void set(int red, int green, int blue, String name) {...} public synchronized int getRGB() {...} public synchronized String getName() {...} public synchronized void invert() {...} } * Guidelines: 1) No setters 2) All fields final and private 3) No subclassing allowed 4) Don't have mutable objects as fields. 17.3) how can the last directive be met? 18) How to fix the deadlock in the Deadlock class? - See the Safelock.java file.