用主类归并线程
在上面的例子中,我们看到线程类(Thread)与措施的主类(Main)是脱离开的。这样做很是公道,并且易于领略。然而,尚有另一种方法也是常常要用到的。尽量它不十理解确,但一般都要更简捷一些(这也表明白它为什么十分风行)。通过将主措施类酿成一个线程,这种形式可将主措施类与线程类归并到一起。由于对一个GUI措施来说,主措施类必需从Frame或Applet担任,所以必需用一个接口插手特另外成果。这个接口叫作Runnable,个中包括了与Thread一致的根基要领。事实上,Thread也实现了Runnable,它只指出有一个run()要领。
对归并后的措施/线程来说,它的用法不是十理解确。当我们启动措施时,会建设一个Runnable(可运行的)工具,但不会自行启动线程。线程的启动必需明晰举办。下面这个措施向我们演示了这一点,它再现了Counter2的成果:
//: Counter3.java
// Using the Runnable interface to turn the
// main class into a thread.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Counter3
extends Applet implements Runnable {
private int count = 0;
private boolean runFlag = true;
private Thread selfThread = null;
private Button
onOff = new Button("Toggle"),
start = new Button("Start");
private TextField t = new TextField(10);
public void init() {
add(t);
start.addActionListener(new StartL());
add(start);
onOff.addActionListener(new OnOffL());
add(onOff);
}
public void run() {
while (true) {
try {
selfThread.sleep(100);
} catch (InterruptedException e){}
if(runFlag)
t.setText(Integer.toString(count++));
}
}
class StartL implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(selfThread == null) {
selfThread = new Thread(Counter3.this);
selfThread.start();
}
}
}
class OnOffL implements ActionListener {
public void actionPerformed(ActionEvent e) {
runFlag = !runFlag;
}
}
public static void main(String[] args) {
Counter3 applet = new Counter3();
Frame aFrame = new Frame("Counter3");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
此刻run()位于类内,但它在init()竣事今后仍处在“睡眠”状态。若按下启动按钮,线程便会用几多有些暧昧的表达方法建设(若线程尚不存在):
new Thread(Counter3.this);
若某样对象有一个Runnable接口,实际只是意味着它有一个run()要领,但不存在与之相关的任何非凡对象——它不具有任何天生的线程处理惩罚本领,这与那些从Thread担任的类是差异的。所觉得了从一个Runnable工具发生线程,必需单独建设一个线程,并为其通报Runnable工具;可为其利用一个非凡的构建器,并令其回收一个Runnable作为本身的参数利用。随后便可为谁人线程挪用start(),如下所示:
selfThread.start();
它的浸染是执行通例初始化操纵,然后挪用run()。
Runnable接口最大的一个利益是所有对象都从属于沟通的类。若需会见什么对象,只需简朴地会见它即可,不需要涉及一个独立的工具。但为这种便利也是要支付价钱的——只可为谁人特定的工具运行单唯一个线程(尽量可建设那种范例的多个工具,可能在差异的类里建设其他工具)。
留意Runnable接口自己并不是造成这一限制的祸首罪魁。它是由于Runnable与我们的主类归并造成的,因为每个应用只能主类的一个工具。