java如何创建启动线程
编译并运行下面程序代码,结果是什么?
public class MyClass extends Thread { public MyClass(String s){ msg=s; } String msg; public void run(){ System.out.println(msg); } public static void main(String[] args) { new MyClass("Hello"); new MyClass("World"); } }
请选择正确的答案:
(a)程序不能被编译。
(b)可以编译,每次运行时依次打印出Hello和World。
(c)可以编译,并打印一个永远不结束的Hello和World。
(d)可以编译,运行时打印Hello和World,但顺序不可预测。
(e)可以编译,运行时不输出任何内容,并终止。
考点:考察求职者对创建线程并启动线程的掌握。
出现频率:★★★★
【面试题解析】
创建线程有两种方式。
1.继承java.lang.Thread类
class ThreadTest extends Thread{ public void run() { System.out.println ("someting run here!"); } public void run(String s){ System.out.println ("string in run is " + s); } public static void main (String[] args) { ThreadTest tt = new ThreadTest(); tt.start(); tt.run("it won't auto run!"); } }
输出的结果:
string in run is it won't auto run! someting run here!
注意输出的顺序:是否与想象的顺序相反了?为什么呢?一旦调用start()方法,必须给JVM留足时间,让它配置进程。而在JVM配置完成之前,重载的run(String s)方法被调用了,结果反而先输出了“string in run is it won't auto run!”。之后,tt线程完成了配置,输出了“someting run here!”。
这个结论是比较容易验证的。
修改上面的程序,在“tt.start();”语句后面加上语句“for (int i = 0; i<10000;i++);”。主线程必须执行运算量比较大的for循环,只有执行完for循环,才能运行后面的“tt.run("it won't auto run!");”语句。此时,因为有足够的时间完成线程的配置,所以修改后的程序运行结果如下:
someting run here! string in run is it won't auto run!
注意:这种输出结果的顺序是没有保障!不要依赖循环耗时!
Thread类中有许多管理线程的方法,包括创建、启动和暂停它们,所有的操作都是从run()方法开始,并且在run()方法内编写需要在独立线程内执行的代码。run()方法可以调用其他方法,但是执行的线程总是通过调用run()开始。
没有参数的run()方法是自动被调用的,而带参数的run()是被重载的,必须显式调用。
上面示例中创建线程的方式很简单,但不是最好的方案。Java是单继承结构的,如果继承了Thread类,那么就不能继承其他的类了,应该把继承的机会留给别的类。
2.实现java.lang.Runnable接口
class ThreadTest implements Runnable { public void run() { System.out.println ("someting run here"); } public static void main (String[] args) { ThreadTest tt = new ThreadTest(); Thread t1 = new Thread(tt); Thread t2 = new Thread(tt); t1.start(); t2.start(); //new Thread(tt).start(); } }
这种方式把线程相关的代码和线程要执行的代码分离开来。
另一种方式是参数式匿名内部类,示例代码如下:
class ThreadTest{ public static void main (String[] args) { Thread t = new Thread(new Runnable(){ public void run(){ System.out.println ("anonymous thread"); } }); t.start(); } }
在调用start()方法开始执行线程之前,线程的状态还不是活的。测试程序如下:
class ThreadTest implements Runnable { public void run() { System.out.println ("someting run here"); } public static void main (String[] args) { ThreadTest tt = new ThreadTest(); Thread t1 = new Thread(tt); System.out.println (t1.isAlive()); t1.start(); System.out.println (t1.isAlive()); } }
结果输出:
false true
isAlive()方法用于确定一个线程是否已经启动,而且还没完成run()方法。
注意:线程的启动要调用start()方法,只有这样才能创建新的调用栈。而直接调用run()方法的话,就不会创建新的调用栈,也就不会创建新的线程,run()方法就与普通的方法没什么两样了。
参考答案:(d)。