在Java中,实现多线程操作有两种方式,一种是继承java.lang包下的Thread类,覆写Thread类的run()方法,在run()方法中实现运行在线程上的代码。
另一种就是实现java.lang.Runnable接口,同样是在run()方法中实现运行在线程上的代码。两种方式的区别在于,继承Thread类可以直接启动线程,实现Runnable接口不能直接启动线程,需要先创建Thread类的实例对象,通过Thread类的构造方法传入实现了Runnable接口的实例对象,然后通过Thread类来启动线程。因此,这两种方式都会用到Thread类,由此可见该类在多线程中的重要性,接下来就通过一些实例针对Java中多线程的两种创建方式分别进行讲解,并比较它们的优缺点。
创建线程的第一种方式----继承Thread类,代码如下所示:
public class Example02 {
publicstatic void main(String[] args) {
Clientt2=new Client();
t2.start();
while(true) {
System.out.println(Thread.currentThread().getName()
+"................... Client2 is running");
}
}
}
class Client extends Thread {
publicvoid run() {
while(true) {
System.out.println(Thread.currentThread().getName()
+ "...................Client1 isrunning");
}
}
}
例程中,Client类继承了Thread类,也就具有了Thread类的全部特点,在main()方法中创建Client的实例对象,并调用从Thread类继承的start()方法开启线程,两个while循环处的代码交替运行。为了方便看出哪个线程正在运行,可以通过Thread.currentThread().getName()方法获得当前线程的名称,默认情况下,主线程的名称为main,用户启动的多条线程的名称依次为Thread-0、Thread-1、Thread-2……Thread-n等。接下来通过单线程和多线程运行的流程图来说明它们的区别,如下图所示。
从图中可知,单线程中,main()方法必须等到Client的print()方法返回后才能继续运行,而在多线程中,main()方法和Client的run()方法运行在各自的线程中,互不影响。这就好比一个1G的CPU分成了两个500M的CPU,在一个CPU上运行main()方法,另一个CPU上运行Client的run()方法。
大家可能会有这样的疑问:程序没有直接调用Client对象的run()方法,而是调用了该对象从Thread类继承来的start()方法,那为什么会执行run()方法呢? 这是因为start()方法有两个作用,一是开启一个新的线程,二是调用Thread子类对象的run()方法。如果直接调用线程对象的run()方法,线程对象只是一个普通类的实例对象,新的线程并没有开启,run()方法中的代码也只会在主线程中执行。