1、implements Runnable 创建线程
实现步骤:
(1) 定义一个线程类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2) 创建一个Thread类的对象,实现Runnable接口。
(3) 调用Thread对象的start()方法,启动线程,隐含地调用了run()方法。
例程代码:
运行结果:
简单分析:
从上图可以看出,在这个例程中,两个线程其实是共享了一个count变量资源,都可以对count进行减法操作。当count减为0时,两个线程都退出了。故一共做了10次减法。
2、extends Thread 创建线程
实现步骤:
(1) 首先定义一个类去继承Thread类,重写父类中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2) 然后在初始化线程时,new一个子类的对象。
(3) 调用start方法,启动线程,隐含地调用了run()方法。
例程代码:
运行结果:
简单分析:
从上图就可以看出二者的差异了。采用继承Thread类方法实现的两个线程并没有共享count变量,而是各自取到了count变量的副本,并各自做了10次减法,当属于自己的count变为0时,退出线程。
3、两种实现方式的比较
根据以上分析我们可以知道,使用实现Runnable接口方式创建的线程会共享同一个目标对象,实现了多个相同线程处理同一份资源;而使用继承Thread类方式创建的线程则是各自持有一个资源对象的副本,只对自己的副本资源进行处理。
由此,我们可以总结出如下的差异:
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。