Welcome to EZDefinition.com
Technological Concepts, Abbreviations & Definitions
Main Menu
Main categories
  • Operating Systems
  • Computer Hardware
  • Internet
  • Programming Languages
  • Multimedia
  • Software
  • Security and Encryption
  • Communications and Networking
  • Organizations
  • Books
  • Databases
  • Games
  • E-commerce

    [an error occurred while processing this directive]

  • EZDefinition Sponsor
    Please visit our sponsor Parosoft.com
    Related Links to Runnable revisited
    [an error occurred while processing this directive]
    Runnable revisited
    [an error occurred while processing this directive]
    Computer Technologies  Programming Languages  Java Runnable revisited

    Runnable revisited

    Runnable revisited

    Earlier in this chapter, I suggested that you think carefully before making an applet or main Frame as an implementation of Runnable. Of course, if you must inherit from a class and you want to add threading behavior to the class, Runnable is the correct solution. The final example in this chapter exploits this by making a Runnable JPanel class that paints different colors on itself. This application is set up to take values from the command line to determine how big the grid of colors is and how long to sleep( ) between color changes. By playing with these values you’ll discover some interesting and possibly inexplicable features of threads:
    //: c14:ColorBoxes.java
    // Using the Runnable interface.
    // <applet code=ColorBoxes width=500 height=400>
    // <param name=grid value="12">
    // <param name=pause value="50">
    // </applet>
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import com.bruceeckel.swing.*;

    class CBox extends JPanel implements Runnable {
    private Thread t;
    private int pause;
    private static final Color[] colors = {
    Color.black, Color.blue, Color.cyan,
    Color.darkGray, Color.gray, Color.green,
    Color.lightGray, Color.magenta,
    Color.orange, Color.pink, Color.red,
    Color.white, Color.yellow
    };
    private Color cColor = newColor();
    private static final Color newColor() {
    return colors[
    (int)(Math.random() * colors.length)
    ];
    }
    public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(cColor);
    Dimension s = getSize();
    g.fillRect(0, 0, s.width, s.height);
    }
    public CBox(int pause) {
    this.pause = pause;
    t = new Thread(this);
    t.start();
    }
    public void run() {
    while(true) {
    cColor = newColor();
    repaint();
    try {
    t.sleep(pause);
    } catch(InterruptedException e) {
    System.err.println("Interrupted");
    }
    }
    }
    }

    public class ColorBoxes extends JApplet {
    private boolean isApplet = true;
    private int grid = 12;
    private int pause = 50;
    public void init() {
    // Get parameters from Web page:
    if (isApplet) {
    String gsize = getParameter("grid");
    if(gsize != null)
    grid = Integer.parseInt(gsize);
    String pse = getParameter("pause");
    if(pse != null)
    pause = Integer.parseInt(pse);
    }
    Container cp = getContentPane();
    cp.setLayout(new GridLayout(grid, grid));
    for (int i = 0; i < grid * grid; i++)
    cp.add(new CBox(pause));
    }
    public static void main(String[] args) {
    ColorBoxes applet = new ColorBoxes();
    applet.isApplet = false;
    if(args.length > 0)
    applet.grid = Integer.parseInt(args[0]);
    if(args.length > 1)
    applet.pause = Integer.parseInt(args[1]);
    Console.run(applet, 500, 400);
    }
    } ///:~
    ColorBoxes is the usual applet/application with an init( ) that sets up the GUI. This sets up the GridLayout so that it has grid cells in each dimension. Then it adds the appropriate number of CBox objects to fill the grid, passing the pause value to each one. In main( ) you can see how pause and grid have default values that can be changed if you pass in command-line arguments, or by using applet parameters.
    CBox is where all the work takes place. This is inherited from JPanel and it implements the Runnable interface so each JPanel can also be a Thread. Remember that when you implement Runnable, you don’t make a Thread object, just a class that has a run( ) method. Thus, you must explicitly create a Thread object and hand the Runnable object to the constructor, then call start( ) (this happens in the constructor). In CBox this thread is called t.
    Notice the array colors, which is an enumeration of all the colors in class Color. This is used in newColor( ) to produce a randomly selected color. The current cell color is cColor.
    paintComponent( ) is quite simple—it just sets the color to cColor and fills the entire JPanel with that color.
    In run( ), you see the infinite loop that sets the cColor to a new random color and then calls repaint( ) to show it. Then the thread goes to sleep( ) for the amount of time specified on the command line.
    Precisely because this design is flexible and threading is tied to each JPanel element, you can experiment by making as many threads as you want. (In reality, there is a restriction imposed by the number of threads your JVM can comfortably handle.)
    This program also makes an interesting benchmark, since it can show dramatic performance differences between one JVM threading implementation and another.

    Too many threads

    At some point, you’ll find that ColorBoxes bogs down. On my machine, this occurred somewhere after a 10 x 10 grid. Why does this happen? You’re naturally suspicious that Swing might have something to do with it, so here’s an example that tests that premise by making fewer threads. The following code is reorganized so that an ArrayList implements Runnable and that ArrayList holds a number of color blocks and randomly chooses ones to update. Then a number of these ArrayList objects are created, depending roughly on the grid dimension you choose. As a result, you have far fewer threads than color blocks, so if there’s a speedup we’ll know it was because there were too many threads in the previous example:
    //: c14:ColorBoxes2.java
    // Balancing thread use.
    // <applet code=ColorBoxes2 width=600 height=500>
    // <param name=grid value="12">
    // <param name=pause value="50">
    // </applet>
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import com.bruceeckel.swing.*;

    class CBox2 extends JPanel {
    private static final Color[] colors = {
    Color.black, Color.blue, Color.cyan,
    Color.darkGray, Color.gray, Color.green,
    Color.lightGray, Color.magenta,
    Color.orange, Color.pink, Color.red,
    Color.white, Color.yellow
    };
    private Color cColor = newColor();
    private static final Color newColor() {
    return colors[
    (int)(Math.random() * colors.length)
    ];
    }
    void nextColor() {
    cColor = newColor();
    repaint();
    }
    public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(cColor);
    Dimension s = getSize();
    g.fillRect(0, 0, s.width, s.height);
    }
    }

    class CBoxList
    extends ArrayList implements Runnable {
    private Thread t;
    private int pause;
    public CBoxList(int pause) {
    this.pause = pause;
    t = new Thread(this);
    }
    public void go() { t.start(); }
    public void run() {
    while(true) {
    int i = (int)(Math.random() * size());
    ((CBox2)get(i)).nextColor();
    try {
    t.sleep(pause);
    } catch(InterruptedException e) {
    System.err.println("Interrupted");
    }
    }
    }
    public Object last() { return get(size() - 1);}
    }

    public class ColorBoxes2 extends JApplet {
    private boolean isApplet = true;
    private int grid = 12;
    // Shorter default pause than ColorBoxes:
    private int pause = 50;
    private CBoxList[] v;
    public void init() {
    // Get parameters from Web page:
    if (isApplet) {
    String gsize = getParameter("grid");
    if(gsize != null)
    grid = Integer.parseInt(gsize);
    String pse = getParameter("pause");
    if(pse != null)
    pause = Integer.parseInt(pse);
    }
    Container cp = getContentPane();
    cp.setLayout(new GridLayout(grid, grid));
    v = new CBoxList[grid];
    for(int i = 0; i < grid; i++)
    v[i] = new CBoxList(pause);
    for (int i = 0; i < grid * grid; i++) {
    v[i % grid].add(new CBox2());
    cp.add((CBox2)v[i % grid].last());
    }
    for(int i = 0; i < grid; i++)
    v[i].go();
    }
    public static void main(String[] args) {
    ColorBoxes2 applet = new ColorBoxes2();
    applet.isApplet = false;
    if(args.length > 0)
    applet.grid = Integer.parseInt(args[0]);
    if(args.length > 1)
    applet.pause = Integer.parseInt(args[1]);
    Console.run(applet, 500, 400);
    }
    } ///:~
    In ColorBoxes2 an array of CBoxList is created and initialized to hold grid CBoxLists, each of which knows how long to sleep. An equal number of CBox2 objects is then added to each CBoxList, and each list is told to go( ), which starts its thread.
    CBox2 is similar to CBox: it paints itself with a randomly chosen color. But that’s all a CBox2 does. All of the threading has been moved into CBoxList.
    The CBoxList could also have inherited Thread and had a member object of type ArrayList. That design has the advantage that the add( ) and get( ) methods could then be given specific argument and return value types instead of generic Objects. (Their names could also be changed to something shorter.) However, the design used here seemed at first glance to require less code. In addition, it automatically retains all the other behaviors of an ArrayList. With all the casting and parentheses necessary for get( ), this might not be the case as your body of code grows.
    As before, when you implement Runnable you don’t get all of the equipment that comes with Thread, so you have to create a new Thread and hand yourself to its constructor in order to have something to start( ), as you can see in the CBoxList constructor and in go( ). The run( ) method simply chooses a random element number within the list and calls nextColor( ) for that element to cause it to choose a new randomly selected color.
    Upon running this program, you see that it does indeed run faster and respond more quickly (for instance, when you interrupt it, it stops more quickly), and it doesn’t seem to bog down as much at higher grid sizes. Thus, a new factor is added into the threading equation: you must watch to see that you don’t have “too many threads” (whatever that turns out to mean for your particular program and platform—here, the slowdown in ColorBoxes appears to be caused by the fact that there’s only one thread that is responsible for all painting, and it gets bogged down by too many requests). If you have too many threads, you must try to use techniques like the one above to “balance” the number of threads in your program. If you see performance problems in a multithreaded program you now have a number of issues to examine:
    1. Do you have enough calls to sleep( ), yield( ), and/or wait( )?
    2. Are calls to sleep( ) long enough?
    3. Are you running too many threads?
    4. Have you tried different platforms and JVMs?
    Issues like this are one reason that multithreaded programming is often considered an art


    [an error occurred while processing this directive]

    [an error occurred while processing this directive]
     

    All Rights Reserved

    Terms of usage   Please read our privacy stetment
    Copyright © 1999-2006 EZDefinition.com

     

    [an error occurred while processing this directive]