A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© jagon 中级黑马   /  2014-3-12 11:27  /  792 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

继承Thread类实现多线程
         java.lang.Thread是一个负责线程操作的类,任何的类只需要继承了Thread类就可以成为一个线程的主类,但是既然是主类必须有它的使用方法,而线程启动的主方法是需要覆写Thread类中的run()方法才可以。
范例:定义一个线程的主体类
class MyThread extends Thread { // 线程的主体类
    private String title;
    public MyThread(String title) {
        this.title = title;
    }
    @Override
    public void run() { // 线程的主方法
        for (int x = 0; x < 50; x++) {
            System.out.println(this.title + "运行,x = " + x);
        }
    }
}
         现在按照道理来讲,已经出现了线程类,并且里面也存在了相应的操作方法,那么就应该产生对象并调用里面的方法,自然下面编写出了下的程序。
public class TestDemo {
    public static void main(String[] args) throws Exception {
        MyThread mt1 = new MyThread("线程A") ;
        MyThread mt2 = new MyThread("线程B") ;
        MyThread mt3 = new MyThread("线程C") ;
        mt1.run() ;
        mt2.run() ;
        mt3.run() ;
    }
}
         但是以上的操作实话而言并没有真正的启动多线程,因为多个线程彼此之间的执行一定是交替的方式运行,而此时是顺序执行,即:每一个对象的代码执行完之后才向下继续执行。如果要想在程序之中真正的启动多线程,必须依靠Thread类的一个方法:public void start(),表示真正启动多线程,调用此方法后会间接调用run()方法。
public class TestDemo {
    public static void main(String[] args) throws Exception {
        MyThread mt1 = new MyThread("线程A") ;
        MyThread mt2 = new MyThread("线程B") ;
        MyThread mt3 = new MyThread("线程C") ;
        mt1.start() ;
        mt2.start() ;
        mt3.start() ;
    }
}
         此时可以发现,多个线程之间彼此交替执行,但是每次的执行结果肯定是不一样的。通过以上的代码就可以得出结论:要想启动线程必须依靠Thread类的start()方法执行,线程启动之后会默认调用了run()方法。
疑问?为什么线程启动的时候必须调用start()而不是直接调用run()?
         发现调用了start()之后,实际上它执行的还是覆写后的run()方法,那为什么不直接调用run()方法呢?那么为了解释此问题,下面打开Thread类的源代码,观察一下start()方法的定义。
    public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }
    private native void start0();
         打开此方法的实现代码首先可以发现方法会抛出一个“IllegalThreadStateException”异常。按照之前所学习的方式来讲,如果一个方法之中使用了throw抛出一个异常对象,那么这个异常应该使用try…catch捕获,或者是方法的声明上使用throws抛出,但是这块都没有,因为这个异常类是属于运行时异常(RuntimeException)的子类。
java.lang.Object
         |- java.lang.Throwable
                   |- java.lang.Exception
                            |- java.lang.RuntimeException
                                     |- java.lang.IllegalArgumentException
                                               |- java.lang.IllegalThreadStateException
         当一个线程对象被重复启动之后会抛出此异常,即:一个线程对象只能启动唯一的一次。在start()方法之中有一个最为关键的部分就是start0()方法,而且这个方法上使用了一个native关键字的定义。
         native关键字指的是Java本地接口调用(Java Native Interface),即:是使用Java调用本机操作系统的函数功能完成一些特殊的操作,而这样的代码开发在Java之中几乎很少出现,因为Java的最大特点是可移植性,如果一个程序只能在固定的操作系统上使用,那么可移植性就将彻底的丧失,所以,此操作一般只作为兴趣使用。
         多线程的实现一定需要操作系统的支持,那么以上的start0()方法实际上就和抽象方法很类似没有方法体,而这个方法体交给JVM去实现,即:在windows下的JVM可能使用A方法实现了start0(),而在linux下的JVM可能使用了B方法实现了start0(),但是在调用的时候并不会去关心具体是何方式实现了start0()方法,只会关心最终的操作结果,交给JVM去匹配了不同的操作系统。
         所以在多线程操作之中,使用start()方法启动多线程的操作是需要进行操作系统函数调用的。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马