前面的程序只创建了一个子线程,实际上一个程序可以创建任意多个线程.例如,下面的程序就创建了三个子线程:
public class test2 { // @param args public static void main(String args[]) { MyThread mt1 = new MyThread("child#1"); MyThread mt2 = new MyThread("child#2"); MyThread mt3 = new MyThread("child#3"); Thread newThrd1 = new Thread(mt1); newThrd1.start(); Thread newThrd2 = new Thread(mt2); newThrd2.start(); Thread newThrd3 = new Thread(mt3); newThrd3.start(); for(int i=0;i<50;i++) { System.out.print("."); try { Thread.sleep(100); }catch(InterruptedException exc) { System.out.println("main thread interrupted"); } } System.out.println("main thread ending"); } } class MyThread implements Runnable { String thrdName; MyThread(String name) { thrdName = name; } public void run() { System.out.println(thrdName+" start"); try { for(int count=0;count<10;count++) { Thread.sleep(400); System.out.println(thrdName+" count is "+count); } }catch(InterruptedException exc) { System.out.println(thrdName+" interrupted"); } } }
输出如下所示:
child#1 start child#2 start child#3 start .....child#2 count is 0 child#3 count is 0 child#1 count is 0 ....child#3 count is 1 child#2 count is 1 child#1 count is 1 ....child#2 count is 2 child#3 count is 2 child#1 count is 2 ...child#2 count is 3 child#1 count is 3 .child#3 count is 3 ....child#2 count is 4 child#1 count is 4 child#3 count is 4 ....child#3 count is 5 child#2 count is 5 child#1 count is 5 ...child#3 count is 6 child#1 count is 6 .child#2 count is 6 ...child#3 count is 7 .child#2 count is 7 child#1 count is 7 ....child#2 count is 8 child#1 count is 8 child#3 count is 8 ....child#3 count is 9 child#2 count is 9 child#1 count is 9 .........main thread ending
如你所见,一旦主线程启动,三个子线程都将共享CPU,注意线程按照被出罕见的顺序启动,然而,情况不总是这样,Java可以以自己的方式自由调度线程的执行.当然,由于时间或环境的不同,程序的具体输出可能会不尽相同,所以如果测试程序时发现有些许不同,也不必大惊小怪.
问:为什么在Java中创建子线程有两种方法(通过扩展线程或实现Tunnable接口),使用哪种方法更合适呢?
答:Thread类定义了几个派生类可以重写的方法.在这些方法中,必须被重写的一个方法是run().当然,在实现runnable接口时也需要重写该方法.一些Java程序员认为仅在通过某些方式增强或修改类时才应该扩展这些类,因此,如果不重写Thread的任何其他方法,最好实现Runnable接口.另外,实现tunnable接口可以让线程继承除Thread类外的其他类.