Java创建线程(Runnable接口和Thread类)
周sir |
2015年4月13日 |
多线程编程 |
0 条评论 | 1473
多数情况通过实例化一个 Thread 对象来创建线程。Java 定义了两种方式:实现 Runnable 接口,或继承 Thread 类。
| 方式 |
入口 |
适用 |
| implements Runnable |
new Thread(this, name) 再 start() |
不必改 Thread 其他方法时优先 |
| extends Thread |
super(name) 后 start(),重写 run() |
确实要增强 / 修改 Thread 时 |
一、实现 Runnable
最简单的办法是写一个实现 Runnable 的类。Runnable 抽象了一个执行代码单元。只需实现 public void run()。run 里可以像主线程一样调其他方法、引用其他类、声明变量;唯一不同是它确立了另一条并发入口。run 返回,该线程结束。
然后在类里实例化 Thread。常用构造函数:Thread(Runnable threadOb, String threadName)。新线程建好后并不会跑,直到调用 void start()——本质上 start 会去调 run。
// Create a second thread.
class NewThread implements Runnable {
Thread t;
NewThread() {
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start();
}
public void run() {
try {
for (int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo {
public static void main(String args[]) {
new NewThread();
try {
for (int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
构造函数里 new Thread(this, "Demo Thread") 表示新线程要调 this 上的 run。start 之后构造函数返回 main,主线程进入自己的 for。两条线程共享 CPU,直到各自循环结束。典型输出:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
多线程里通常主线程应最后结束。一些老 JVM 若主线程先于子线程结束,运行时可能“挂起”。本例主线程 sleep 1000ms、子线程 500ms,保证子线程先完。后面会讲更好的等待方式(join)。
二、扩展 Thread
另一个途径是新建类扩展 Thread,再创建实例。必须重载 run 作为入口,并调用 start 启动。用 super("Demo Thread") 调用 public Thread(String threadName)。
class NewThread extends Thread {
NewThread() {
super("Demo Thread");
System.out.println("Child thread: " + this);
start();
}
public void run() {
try {
for (int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ExtendThread {
public static void main(String args[]) {
new NewThread();
try {
for (int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
输出与前一版相同。子线程由实例化 NewThread(派生自 Thread)生成。
三、选哪一种
Thread 定义了多种可被派生类重载的方法,但必须重载的只有 run——这也是 Runnable 要求的那一个。很多 Java 程序员认为:类只在被加强或修改时才应该被扩展。因此若不重载 Thread 的其他方法,最好只实现 Runnable。本章其余部分用实现 Runnable 的类来创建线程。
一句话总结:run 写线程体,start 才启动;能实现 Runnable 就别去继承 Thread,主线程用更长的 sleep(或后面的 join)保证最后退出。
转载请注明来源:Java创建线程(Runnable接口和Thread类)
我是周sir,这是我的博客。致力于分享我学会的技术和优秀的文章。微信公众号 “周sir专栏” 欢迎大家关注。