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