用主类归并线程
在上面的例子中,我们看到线程类(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与我们的主类归并造成的,因为每个应用只能主类的一个工具。