在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的,是一个具体的类,不是抽象类。该类封装了线程的行为,创建线程的时候,我们只要在继承了Thread类的同时覆写了该类中的run()方法就可以实现多线程操作。但是用户并不能直接调用run()函数,而是调用 Thread 的 start() 函数,该函数再调用 run()方法。但是一个类只能继承一个父类,这是此方法的局限。下面写个代码,让我们来看看它的用法:
但是,此时的结果是很有规律的,先执行第一个对象,然后执行第二个对象,并没有体现出多线程的效果,看下面的结果:
这是为什么呢?从Jdk 文档中,我们找到了start()方法的原方法声明,一旦执行start 方法,就会调用run()
我们把上面的程序稍作修改如下:
我们再来看看这次修改后的执行结果:
显然,使用start 方法可以实现Java的多线程机制,看上面的结果图,程序不是可以乱序执行了?那么为什么要使用start方法来启动多线程呢?start 方法又是怎么实现的?它的内部原理是什么?带着这些问题,我们来一步一步剖析Java 的源代码。
因为使用了native 关键字来声明start 方法,什么是native method ?简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,一般是C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。因为native method 方法,使得start() 可以直接调用系统底层的许多函数,这就是所谓的JNI技术(java Native Interface)
class MyThreadDemo extends Thread{ private String name; public MyThreadDemo(String name) { super(); this.name = name; } public void run(){ for(int i=0;i<10;i++){ System.out.println("线程开始:"+this.name+",i="+i); } } } public class MyThread { public static void main(String[] args){ MyThreadDemo mt1=new MyThreadDemo("线程a"); MyThreadDemo mt2=new MyThreadDemo("线程b"); mt1.run(); mt2.run(); } } |
但是,此时的结果是很有规律的,先执行第一个对象,然后执行第二个对象,并没有体现出多线程的效果,看下面的结果:
这是为什么呢?从Jdk 文档中,我们找到了start()方法的原方法声明,一旦执行start 方法,就会调用run()
startpublic void start()使该线程开始执行;Java 虚拟机调用该线程的run 方法。 结果是两个线程并发地运行;当前线程(从调用返回给 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。 |
我们把上面的程序稍作修改如下:
public static void main(String[] args) { MyThread mt1=new MyThread("线程a"); MyThread mt2=new MyThread("线程b"); mt1.start(); mt2.start(); } |
显然,使用start 方法可以实现Java的多线程机制,看上面的结果图,程序不是可以乱序执行了?那么为什么要使用start方法来启动多线程呢?start 方法又是怎么实现的?它的内部原理是什么?带着这些问题,我们来一步一步剖析Java 的源代码。
因为使用了native 关键字来声明start 方法,什么是native method ?简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,一般是C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。因为native method 方法,使得start() 可以直接调用系统底层的许多函数,这就是所谓的JNI技术(java Native Interface)