A Simple Clock Applet
import java.awt.*;
import java.applet.*;
import java.util.*;
public class Clock0 extends Applet {
public void paint(Graphics g) {
String display = new Date() + "";
FontMetrics fm = g.getFontMetrics();
int stringWidth = fm.stringWidth(display);
int screenWidth = getWidth();
g.drawString(display, (screenWidth - stringWidth)/2, 100);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
repaint();
}
}
Thread.sleep - causes the application to sleep for specified milliseconds (1000ths of a second).
paint is called it updates the display and calls repaint
A Related Applet: A Stopwatch
import java.util.*;
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.text.*;
public class Clock1 extends Applet implements ActionListener {
public void init() {
setLayout(new FlowLayout(FlowLayout.CENTER));
clock = new Label(simpleDateFormat.format(new Date(0)));
add(clock);
b = new Button("Start");
add(b);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
paused = !paused;
if (!paused) {
b.setLabel("Pause");
if (firstTime) {
firstTime = false;
startClock();
}
}
else
b.setLabel("Resume");
}
void startClock() {
Date startDate = new Date();
while (true) {
if (!paused) {
Date duration = new Date(new Date().getTime() - startDate.getTime());
clock.setText(simpleDateFormat.format(duration));
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss");
boolean paused = true;
Button b;
Label clock;
boolean firstTime = true;
}
startClock to be invoked
startClock contains infinite loop
actionPerformed...
actionPerformed never returns to whoever called it ...
Creating a Running a Thread
Either:
Thread
Runnable interface
Thread
run method
start method
start and run
Fixing the Stopwatch
startClock
Diag class that helps us see who's doing what
Diag contains a single static method that accepts a message and prints it together
with the name of the currently executing thread
class Diag {
static void threadPrint(String what) {
System.err.println(what + ": " + Thread.currentThread().getName());
}
}
Here's the Applet
import java.util.*;
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.text.*;
public class Clock2 extends Applet implements ActionListener {
public void init() {
Diag.threadPrint("init");
setLayout(new FlowLayout(FlowLayout.CENTER));
Label clock = new Label(simpleDateFormat.format(new Date(0)));
add(clock);
b = new Button("Pause");
b.setForeground(Color.red);
add(b);
b.addActionListener(this);
clockThread = new Clock2Thread(clock);
clockThread.start();
}
public void actionPerformed(ActionEvent e) {
Diag.threadPrint("actionPerformed");
boolean paused = clockThread.togglePaused();
if (!paused) {
b.setForeground(Color.red);
b.setLabel("Pause");
}
else {
b.setForeground(DARK_GREEN);
b.setLabel("Resume");
}
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss");
static final Color DARK_GREEN = new Color(0, 100, 0);
Button b;
Clock2Thread clockThread;
}
Clock2Thread object and the invocation of start
actionPerformed method controls the clock thread via the
togglePaused method
... and here's the thread ...
import java.awt.*;
import java.util.*;
import java.text.*;
class Clock2Thread extends Thread {
Clock2Thread(Label clock) {this.clock = clock;}
boolean togglePaused() {
Diag.threadPrint("togglePaused");
paused = !paused;
return paused;
}
public void run() {
Diag.threadPrint("run");
Date startDate = new Date();
int count = 0;
while (true) {
if (!paused) {
Date duration = new Date(new Date().getTime() - startDate.getTime());
clock.setText(simpleDateFormat.format(duration));
count++;
if (count > 10) {
Diag.threadPrint("tick");
count = 0;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss");
boolean paused = false;
Label clock;
}
Why Threads?
//Dispatcher Thread
while (1) {
request = getNextRequest()
handOffRequest(request)
}
//Worker Thread
while (1) {
request = waitForWork()
found = lookInCache(request, page)
if (!found)
readPageFromDisk(request, page)
returnPage(page)
}
#3 - Inputting, Processing and Outputting Blocks of Data
Preemptive Threads