服务时间:8:30-18:00

首页 >java学习网

java如何创建启动线程

发布时间:2022-11-27 17:06 字数:2543字 阅读:94

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)。