Thread类与Runnable接口
1.继承Thread类并重载run方法
<script language=javascript>
</script>
Thread类:是专门用来创建线程和对线程进行操作的类。Thread中定义了许多方法对线程进行操作。
Thread类在缺省情况下run方法是空的。可以通过继承Thread类并重写Thread类的run方法实现用户线程。
总体结构如下:public class MyThread extends Thread { public void run() { … … } }
MyThread t = new MyThread(); t. start();
见例题:TwoThreadsTest.java
TwoThreadsTest.java:该例子演示了如何通过继承Thread的方法实现线程。该例子同时启动了两个线程。请运行之,注意运行结果class TwoThreadsTest { public static void main (String args[]) { new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start(); } }
class SimpleThread extends Thread { public SimpleThread(String str) { super(str); } public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getName()); try { sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println("DONE! " + getName()); } }
在这个例子中,类 TwoThreadsTest的main( )方法中构造了两个 SimpleThread类的线程,一个称为"Jamaica",另一个为 " Fiji ",并在构造后马上就调用了start( )方法来启动这两个线程。 类SimpleThread是类Thread的子类,它首先定义了一个构造方法,其中自变量为字符串类型,例如上面的" Fiji ", 它的作用就是给线程取名。类SimpleThread中的第二个方法是run( )方法,它覆盖了类Thread中的run( )方法。run( )方法中是一个10次的循环,每次循环中显示循环的次数和当前正运行的线程的名称,然后睡眠一个随机产生的时间间隔。在循环结束后,就显示"DONE!"及线程名。
下面我们来看一下运行结果:
0 Jamaica 0 Fiji 1 Fiji 1 Jamaica 2 Jamaica 2 Fiji 3 Fiji 3 Jamaica 4 Jamaica 4 Fiji 5 Jamaica 5 Fiji 6 Fiji 6 Jamaica 7 Jamaica 7 Fiji 8 Fiji 9 Fiji 8 Jamaica DONE! Fiji 9 Jamaica DONE! Jamaica
可以看到在输出结果中两个线程的名称是混合在一起的,也没有顺序可循,这是因为这两个线程是同时运行的,并且是同时显示输出
2.执行Runnable接口的类实现run方法
<script language=javascript>
</script>
通过建立一个实现了Runnable接口的对象,并以它作为线程的目标对象来创建一个线程。
Runnable接口:定义了一个抽象方法run()。定义如下:
public interface java.lang.Runnable{ public abstract void run(); }
创建的总体框架如下:
class MyRunner implements Runnable { public void run() { … } }
MyRunner r = new MyRunner();
Thread t = new Thread( ThreadGroup group, Runnable target, String name);
见例题:
ThreadTesterer.java ThreadTest.java
例如:
public class Clock extends java.applet.Applet implements Runnable { Thread clockThread; public void start() { if (clockThread == null) { clockThread = new Thread(this, "Clock"); clockThread.start(); } } public void run() { while (clockThread != null) { repaint(); try { clockThread.sleep(1000); } catch (InterruptedException e){ } } } public void paint(Graphics g) { Date now = new Date(); g.drawString(now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(), 5, 10); } public void stop() { clockThread.stop(); clockThread = null; } }
这是一个时钟Applet,它显示当前时间并逐秒进行更新。该Applet利用Runnable接口为其线程提供run()方法。类Clock由类Applet扩展而得,但同时它需要一个线程来实现时间的更新显示。由于Java中不支持多重继承,所以它不能再继承类Thread,而是利用了Runnable接口。 首先,在start()方法中构造了一个名为clockThread的线程 并调用Thread.start()方法来启动这一线程,即在Java运行时建立系统的线程关系。下面这句建立了一个新的线程:
clockThread = new Thread(this, "Clock");
其中this是Thread 构造方法中的第一个自变量,作为该线程的目标对象,它必须实现Runnable接口。在这种构造方法下,线程clockThread就以它的可运行的目标对象中的run()方法为其run()方法,在本例中,这个目标对象就是Clock Applet。构造方法中的第二个变量为线程名。
线程被启动以后,调用目标对象的run()方法,除非线程被停止。在run()方法的循环中,Applet重绘本身,然后睡眠1秒,同时要捕获例外事件并进行处理。
如果你离开显示时钟的这一页,应用程序将调用stop()方法,将线程置空。当你返回时,又会创建一个新的线程。
在具体应用中,采用哪种方法来构造线程体要视情况而定。通常,当一个线程已继承了另一个类时,就应该用第二种方法来构造,即实现Runnable接口。
3.总结:
<script language=javascript>
</script>
1.两种方法均需执行线程的start方法为线程分配必须的系统资源、调度线程运行并执行线程的run方法。
2.在具体应用中,采用哪种方法来构造线程体要视情况而定。通常,当一个线程已继承了另一个类时,就应该用第二种方法来构造,即实现Runnable接口。
3.线程的消亡不建议通过调用一个stop()命令。而是让run()方法自然结束。
见例题: ThreadController.java
关闭