Thread,Runnable的区别
我们创建线程的方式一般来说有两种,首先我们来看看两种启动线程方式的具体实现。
- 第一种继承Thread类,实现run方法,最后调用start方法启动线程。
- 第二种实现Runnable接口,实现run方法,然后调用Thread的有参构造方法,将Runnable的子类对象作为构造方法的参数创建一个Thread对象,最后调用start方法启动线程。
从上面两点来看就能知道这两种方式的不同了。
- 首先,第一点,Thread是类,而Runnable是接口。java中不能同时继承多个类,但是可以实现多个接口。所以相对Runnable来说,Thread方式在抽象开发上来说就局限了一点。
- 其次是第二点,Runnable实现线程的方式需要将Runnable子类对象作为Thread有参构造方法的参数传入,也就是说我们创建多个Thread对象,但是可以用同一个Runnable子类对象作为构造方法参数传入,这样多个线程访问的就是同一个对象的数据和运行同样的代码(也即是同一个任务)。而Thread要直接做到这一点就不行,当然了我说的是直接做到不行,通过其他方式中转一下也是可以的(比如说:用静态变量或者新建一个数据类对象传入就可以达到访问同一个变量),只不过这样就相对麻烦了一些哈!
Thread线程实现
线程类:
package com.example; /** * Created by PICO-USER on 2017/11/8. */ public class MyThread extends Thread { private int number = 5; @Override public void run() { super.run(); synchronized (this) { for (int i = 0; i < 6; i++) { synchronized (MyThread.class) { if (number > 0) { System.out.print(getName() + " number = " + number + "\n"); number--; } } } } } }
主程序入口:
public class MyClass { public static void main(String[] args0) throws InterruptedException { Thread thread = null; for (int i = 0; i < 3; i++) { thread = new MyThread(); thread.setName("Thread_" + i); thread.start(); } } }输出结果:
看看上面的结果,我们用的是非静态变量,所以三个线程操作的是三个不同的对象的数据。但是Runnable方式的就不酱紫了(看下面)。
Runnable线程实现
package com.example; /** * Created by PICO-USER on 2017/11/8. */ public class MyRunnable implements Runnable { public int number = 5; @Override public void run() { String name = Thread.currentThread().getName(); synchronized (this) { for (int i = 0; i < 6; i++) { if (number > 0) { System.out.print(name + " number = " + number + "\n"); number--; } } } } }
主程序入口:
package com.example; import java.util.Properties; public class MyClass { public static void main(String[] args0) throws InterruptedException { Runnable runnable = new MyRunnable(); Thread thread = null; for (int i = 0; i < 3; i++) { thread = new Thread(runnable); thread.start(); } } }输出结果:
总结:很明显,同样的任务,输出的结果却是不一样的。其实说到底,将线程跟类这两个概念分开理解清楚,一切问题也就迎刃而解了。启动线程是去执行任务,任务是run方法中的代码执行,那具体操作的数据,是类中的数据。Thread方式,启动线程的是Thread,操作的数据和执行的任务还是在Thread的子类,而Runnable方式中,启动线程的是Thread类,而操作的数据和执行的任务却是在Runnable子类中。