Question:
I am trying to make an HTML page with many applets running concurrently.Unfortunately, an applet that I created uses up much of the CPU time andslows all the other applets down. Most of the time my applet is justsleeping. I have it set to MIN_PRIORITY. Here is the entire code:
import java.awt.*; import java.applet.*; public class billboard extends java.applet.Applet implements Runnable{ public String Profit = "Profits"; public String Better = "Better Web Sites"; public String Quick = "Quick Service"; Color green = new Color((float)0,(float).5,(float)0); Color ltgreen = new Color((float)0,(float).8,(float)0); Font theFont; int done=0; public void init(){ setBackground(ltgreen); setFont(theFont); done = 1; } public void run(){ Thread billboard = new Thread(this); billboard.setPriority(Thread.MIN_PRIORITY); billboard.start(); repaint(); } public void paint(Graphics g){ g.setColor(green); g.clearRect( 0,0,size().width, size().height); g.drawString(Profit,45,20); try { Thread.sleep(2000); } catch (InterruptedException e) {Thread.yield();}; g.clearRect( 0,0,size().width, size().height); g.drawString(Better,15,20); try { Thread.sleep(2000); } catch (InterruptedException e) {Thread.yield();}; g.clearRect( 0,0,size().width, size().height); g.drawString(Quick,25,20); try { Thread.sleep(2000); } catch (InterruptedException e) {Thread.yield();}; repaint(); } }
Answer:
This is an interesting little puzzle because it shows how the somewhatconfusing directions in the Java documentation can really lead you astray.
When you run the code in this applet, it works fine, alternating betweenthe three strings. However, the code doesn’t actually use a separatethread. You are calling paint() over and over. Each call to paint() isreally busy–it takes up 6 seconds, making the rest of the user interfacethread pretty sluggish. The run() method never executes. (You can put aprint statement into it to verify that it doesn’t get called.)
Let’s fix this up. To have the run() method get called, we need to make anew thread in the start() method:
public class billboard extends java.applet.Applet implements Runnable{ private Thread runner; public void start(){ runner = new Thread(this); runner.start(); } public void stop(){ runner.stop(); } . . . }
Next, let’s think what the run() method of the thread should actually do.It should rotate among the strings and call repaint(). Then it should go tosleep for a little while. That goes on forever (or actually, until thethread is killed.)
public class billboard extends java.applet.Applet implements Runnable{ private String[] messages = new String[3]; private current_message = 0;public void init(){ messages[0] = "Profits"; messages[1] = "Better Web Sites"; messages[2] = "Quick Service"; . . .}public void run(){ while (true) { current_message = (current_message + 1) % messages.length; repaint(); try { Thread.sleep(2000); } catch(InterruptedException e) {} }. . .}
Now the paint() method is short and snappy, as it should be:
public void paint(Graphics g){ g.setColor(green); g.clearRect( 0,0,size().width, size().height); g.drawString(messages[current_message],45,20);}
Try it out–you will find the result much more responsive.
In general, you want to work backwards from the paint() procedure. Eachcall to paint() should do a little bit of work and then return. Itshouldn’t call repaint(). The run() procedure should contain an infiniteloop that sets up the data for the next painting, calls repaint and thensleeps. This recipe lies at the core of all animation applets.