Java Multitasking  «Prev  Next»

Lesson 13

Java Multitasking Conclusion

This module discussesd and explored an application that simulated a town hall meeting and performed multitasking. You learned how to create and start threads and how to supply run() methods for them.
You also learned about Java's synchronized keyword, which helps keep a thread from interfering with another thread by supplying a system of locks for objects and classes. When a thread enters a synchronized method, it acquires a lock, which stops other threads from executing the method at the same time. This can protect data that should be changed only one thread at a time. Last, you learned about the life cycle of a thread, how to put a thread to sleep using wait(), how to wake it up again using notify(), and how to have one thread wait for another thread to complete using join().

Multithreaded Java Application

Even if you do not create a multithreaded Java application, you cannot ignore these concepts. Java technologies like swing in Core Java, Java Servlets in web applications and many Java frameworks implicitly use multithreading techniques and call your code from multiple threads. Developing safe code that works and behaves well in a multithreaded environment demands knowledge about multithreading and synchronization. Multithreading is a complex topic and its coverage in this chapter is limited to the topics covered on the exam. This module also included an introduction to a few threading concepts that you must know to understand the module contents. For the 1Z0-804 exam, you must be able to clearly identify what is guaranteed and what is not by threads. For example, a thread is guaranteed to execute its own code in the sequence in which it is defined. But you cannot guarantee when a thread exactly starts, pauses, or resumes its execution.

Complete application

You might want to read over the complete TownHall application before moving on to make sure you understand how all the multitasking works, now that you have reached the end of this module and seen the whole picture.
Java Town Hall Listing
/* Town Hall - An accurate model or social commentary?
 * Town Hall runs as an applet and illustrates multiple threads.
 */
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

class SynchronizedQueue extends Vector {
  
  private int   count;
  private boolean started;
  private boolean waiting;
  private int   writers;
  
  SynchronizedQueue() {
    count = 0;
    started = false;
  }
  
  public synchronized void checkIn () {
    started = true;
    count++;
  }
  
  public synchronized void checkOut () {
    count--;
    notify();
  }
  
  public synchronized void enqueue(Object elt) {
    super.addElement(elt);
    notify();
  }
  
  public synchronized boolean anyoneLeft() {
    if (!started) return true;
    if (count > 0) return true;
    else return false;
  }
  
  public synchronized Object dequeue() {
    Object ret;
    while (anyoneLeft() && (super.elementCount == 0)) {
      try {
    wait();
      } catch (InterruptedException x) {
      }
    }
    if (super.elementCount > 0) {
      ret = super.firstElement();
      super.removeElement(ret);
    } else {
      ret = null;
    }
    return ret;
  }
}

class Speaker extends Thread {
  int id;
  int speech_count;
  SynchronizedQueue my_soapbox;
  
  static String nouns[] = {
    "dogs", "cats", "elephants", "donkeys", "houses", 
    "monkeys", "cars", "bicycles", "computers", 
    "music", "books" };
  
     static String ends[] = {
       "outlawed", "banned", "imported", "discouraged", 
       "sold", "bought", "given away", "made mandatory", 
       "encouraged", "deported", "exported" };

  Speaker(int new_id, int turns, SynchronizedQueue forum) {
    id = new_id;
    speech_count = turns;
    my_soapbox = forum;
  }

  public void run() {
    int i;
    Random r = new Random();
    my_soapbox.checkIn();
    my_soapbox.enqueue("speaker "+ id +" stepping onto soapbox");
    for (i = 0; i < speech_count; i++) {
      try {
	  	  sleep((r.nextInt() % 10) * 10);
      } 
	     catch (Exception e) {
        e.printStackTrace();      
	     }
      my_soapbox.enqueue("speaker "+ id +": " + nouns[Math.abs(r.nextInt())%nouns.length] +
      " should be " + ends[Math.abs(r.nextInt())%ends.length]);
    }
    my_soapbox.enqueue("speaker "+ id +" stepping off soapbox");
    my_soapbox.checkOut();
  }
}

class MC extends Thread {
  SynchronizedQueue podium;
  TextArea  ta;
  
  MC(SynchronizedQueue new_forum, TextArea ta) {
    podium = new_forum;
    this.ta = ta;
  }
  
  

  public void run() {
    Object utterance;

    ta.append("MC here: good morning.");
    ta.append("\n");
    
    utterance = podium.dequeue();
    while (utterance != null) {             
      ta.append((String)utterance);
      ta.append("\n");
      utterance = podium.dequeue();
    }
    
    ta.append("MC here: good night.");
    ta.append("\n");
  }
}

public class TownHall extends Applet implements ActionListener{
  boolean    running = false;
  boolean    meetingStarted = false;
  MC         georgeWill;
  TextArea   ta;
  Button gavel, clear;
  public void init() {
    setLayout(new BorderLayout());
    ta = new TextArea(10,50);
    add("Center", ta);

    Panel p = new Panel();
    gavel = new Button("pound the gavel");
    clear = new Button("clear the air");
    gavel.addActionListener(this);
    clear.addActionListener(this);
    p.add(gavel);
    p.add(clear);
    add("South", p);
  }
  public void start() {
    if (!running && meetingStarted) {
      georgeWill.resume();
      running = true;
    }
  }
  
  public void stop() {
    if (running) {
      georgeWill.suspend();
      running = false;
    }
  }
  
  public void destroy() {
    georgeWill.stop();
  }

  
  void startNewMeeting() {   
    int num_speakers = 5;
    SynchronizedQueue podium = new SynchronizedQueue();
    Speaker[] contenders = new Speaker[num_speakers];
    
    georgeWill = new MC(podium, ta);
    georgeWill.start();
    
    running = true;
    meetingStarted = true;
    
    for(int i = 0; i < num_speakers; i++) {
      contenders[i] = new Speaker(i, 10, podium);
      contenders[i].start();
    }
    try {
      georgeWill.join();
    } catch (InterruptedException x) {//throw Exception }
    ta.append("Town Hall closing.");
    ta.append("\n");
   
    georgeWill.stop();
    running = false;
    meetingStarted = false;
  }
  
  public void actionPerformed(ActionEvent e) {
    if(e.getSource() == gavel)
      startNewMeeting();
    else
      ta.setText("");
  }
  
}