http://hi.baidu.com/shirdrn/blog/item/7b0a8ed7dfbf11daa144dfb2.html
在Java语言中,创建一个线程类,可以继承Thread类。另外,因为Thread实现了Runnable接口,同时实现了Runnable接口中定义的run方法。可以了解一下:
Runnable接口的定义:
package java.lang;
public interface Runnable {
public abstract void run();
}
Thread类实现了Runnable接口中定义的run方法:
public void run() {
if (target != null) {
target.run();
}
}
其中,target是Thread类中定义的一个私有成员:
private Runnable target;
你可以在Thread类中看到,target默认情况下为null的:
public Thread(String name) {
init(null, null, name, 0);
}
init方法声明如下:
private void init(ThreadGroup g, Runnable target, String name,long stackSize);
所以,默认情况下,如果我们自己实现一个线程类继承自Thread类,即使你自己不重写run方法也是可以的,相当于调用Thread类的run方法执行了一个空操作。
注意,run方法是由系统负责调用的,如果我们去进行调用,那么Java中线程方法体的执行和类的成员方法没什么区别了。
例如:
package org.shirdrn.thread.course1;
public class MyThread extends Thread {
public static void main(String[] args) {
Thread mt = new MyThread();
mt.start();
}
}
正常运行。
实例化一个线程类,然后必须调用start方法才能使该线程的实例执行run方法。
下面我们重写基类Thread定义的run方法:
package org.shirdrn.thread.course1;
import java.util.Date;
public class MyThread extends Thread {
public void run() {
Date date = new Date();
System.out.println(date.toLocaleString());
}
public static void main(String[] args) {
Thread mt = new MyThread();
mt.start();
}
}
运行后输出:
2008-12-31 20:30:41
可以看到,启动线程的时候,线程类的实例确实执行了run方法中代码行。因为,在run方法中也是顺序执行每一行代码,所以输出了一个时间。
当然,可以在run方法中调用线程类的成员方法,实现复杂的操作,如下所示:
package org.shirdrn.thread.course1;
import java.util.Date;
public class MyThread extends Thread {
public void run() {
print();
}
public void print() {
Date date = new Date();
System.out.println(date.toLocaleString());
}
public static void main(String[] args) {
Thread mt = new MyThread();
mt.start();
}
}
调用成员方法print,与上面实现的功能是一样的,输出一个当前时间。
下面实现一个,每经过2秒钟打印出当前时间,其实比较简单,只要在run方法中用一个循环就可以,如下所示:
package org.shirdrn.thread.course1;
import java.util.Date;
public class MyThread extends Thread {
public void run() {
while(true) {
print();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void print() {
Date date = new Date();
System.out.println(date.toLocaleString());
}
public static void main(String[] args) {
Thread mt = new MyThread();
mt.start();
}
}
可以在控制台上看到,程序一直在运行,每隔2秒钟打印一次当前时间:
2008-12-31 20:37:08
2008-12-31 20:37:10
2008-12-31 20:37:12
2008-12-31 20:37:14
2008-12-31 20:37:16
2008-12-31 20:37:18
2008-12-31 20:37:20
2008-12-31 20:37:22
2008-12-31 20:37:24
2008-12-31 20:37:26
2008-12-31 20:37:28
当然也,我们也可以实现Runnable接口,来实现自己的线程类,如下所示:
package org.shirdrn.thread.course1;
import java.util.Date;
public class MyThreadAoo implements Runnable {
@Override
public void run() {
while(true) {
print();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void print() {
Date date = new Date();
System.out.println(date.toLocaleString());
}
public static void main(String[] args) {
Thread mt = new Thread(new MyThreadAoo());
mt.start();
}
}
同上面的运行是一样的,不同的地方,可以看到,在创建一个线程对象的时候,不同于继承Thread类,而是将我们实现的线程类的实例作为Thread的一个参数来构造,然后启动之。
可以看到Thread类的构造方法(一种有8种构造方式):
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
另外,还有7种构造方式:
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
举个例子:
package org.shirdrn.thread.course1;
import java.util.Date;
public class ThreadBoo extends Thread {
public ThreadBoo() {
super();
}
public ThreadBoo(String name) {
super(name);
}
public void run() {
while(true) {
print();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
public void print() {
Date date = new Date();
System.out.println(date.toLocaleString());
}
public static void main(String[] args) {
Thread mt = new ThreadBoo();
mt.start();
//Thread mtt = new ThreadBoo("I-am-100");
//mtt.start();
}
}
使用Thread.currentThread().getName()获取当前正在运行的线程的名称。
当使用默认的线程名时,我们可以看到:
2008-12-31 20:54:34
Thread-0
2008-12-31 20:54:36
Thread-0
2008-12-31 20:54:38
Thread-0
2008-12-31 20:54:40
系统会自动生成线程名Thread-0。
将上面的注释打开,将使用默认线程名的代码注释掉,就会看到我们自己为线程命名,如下所示:
2008-12-31 20:58:52
I-am-100
2008-12-31 20:58:54
I-am-100
2008-12-31 20:58:56
I-am-100
2008-12-31 20:58:58
这里,还没有涉及到共享变量,还是非常基础的,对线程有一个最基本的认识吧。