Thread类与Runnable接口
1.继承Thread类并重载run方法[/url]
Thread类:是专门用来创建线程和对线程进行操作的类。Thread中定义了许多方法对线程进行操作。
Thread类在缺省情况下run方法是空的。可以通过继承Thread类并重写Thread类的run方法实现用户线程。
总体结构如下:
public class MyThread extends Thread {
public void run() {
… …
}
}
MyThread t = new MyThread();
t. start();
见例题:[url=http://blog.csdn.net/duoshanx/admin/chapter6/ThreadController.java]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方法[/url]通过建立一个实现了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);
见例题:
[url=http://blog.csdn.net/duoshanx/admin/chapter6/ThreadTester.java]ThreadTesterer.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.总结:[/url]1.两种方法均需执行线程的start方法为线程分配必须的系统资源、调度线程运行并执行线程的run方法。
2.在具体应用中,采用哪种方法来构造线程体要视情况而定。通常,当一个线程已继承了另一个类时,就应该用第二种方法来构造,即实现Runnable接口。
3.线程的消亡不建议通过调用一个stop()命令。而是让run()方法自然结束。
见例题:[url=http://blog.csdn.net/duoshanx/admin/chapter6/ThreadController.java] ThreadController.java