Thread和Runnable的区别与匿名内部类方式实现线程的创建
Thread和Runnable的区别
如果非要说区别的话,那么就有一下几点
Runnable 和 Thread 创建线程的方式不一样
Runnable 是接口,Thread 是实体类,Thread 和 Runnable 的关系就是实体与实现的关系。
在使用上,如果有复杂的线程操作需求,那就选择继承Thread,如果只是简单的执行一个任务,那就实现Runnable 。
只有一个简单的 run(); 方法;
这个 run 不仅能 run 线程,还有其他东西也能 run(这个是目前的理解,至于其他东西是什么,我也无法举例)
而设置 Runnable 接口的目的就在于:Java 中只能实现单继承,而可以实现多个接口。如果某个类想 run,还行实现其他的,那么就可以通过实现 Runnable 接口完成 run,再实现其他接口或者继承其他类完成 多功能。
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。总结:
实现Runnable接口比继承Thread类所具有的优势:1.适合多个相同的程序代码的线程去共享同一个资源。2.可以避免java中的单继承的局限性。
3.增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。4.线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
扩充∶在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个VM,每一个VM其实在就是在操作系统中启动了一个进程。
如果通过 Runnable 接口创建一个线程,那么应该是这样
class MyThread implements Runnable { @Override public void run() { System.out.println("实现 Runnable 节后后创建线程"); } } public class Test{ // 方法 1 : 通过继承 Runnable 创建线程 public static void main1(String[] args) { // 向上转型 父类引用指向子类对象 Runnable myThread = new MyThread (); Thread thread = new Thread(myThread); thread.start(); } // 方法 2 : 通过 Runnable 匿名内部类创建线程 public static void main2(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("Runnable 匿名内部类创建线程"); } }); thread.start(); } }
通过继承 Thread 创建线程
class MyThread extends Thread { @Override public void run() { System.out.println("继承 Thread 接口创建线程"); } } public class TestDemo2 { // 方法 1 : 继承 Thread 类创建线程 public static void main1(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } // 方法 2 : 匿名内部类创建线程 public static void main2(String[] args) { Thread thread = new Thread() { @Override public void run() { System.out.println("Thread 匿名内部类创建线程"); } }; thread.start(); } }
package Demo01_Sleep; /* 创建多线程程序的第二种方式:实现RunnabLe接口java.Lang. RunnabLe Runnable接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run的无参数方法。 java.Lang.Thread类的构造方法 Thread ( Runnable target)分配新的Thread对象。 Thread ( Runnable target, string name)分配新的Thread对象。 实现步骤: 1.创隍一个Runnable接口的实现类 2.在实现类中重写Runnable接口的run方法,设置线程任务 3.创建一个Runnable接口的实现类对象 4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象 5.调用Thread类中的start方法,开启新的线程执行run方法 实现RunnabLe接口创建多线程程序的好处: 1.避免了单继承的局限性 一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类实现了Runnable接口,还可以继承其他的类,实现其他的接口 2.增强了程序的扩展性,降低了程序的耦合性(解耦) 实现Runnabte接口的方式,把设置线程任务和开启新线程进行了分离(解耦)实现类中,重写了run方法:用来设置线程任务 创建Thread类对象,调用start方法:用来开启线程 */ public class Demo01_Runnble01 { public static void main(String[] args) { //3.创建一个Runnable接口的实现类对象 Demo01_Runnble runnble = new Demo01_Runnble(); //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象 Thread thread = new Thread(runnble); //5.调用Thread类中的start方法,开启新的线程执行run方法 thread.start(); for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+"-->"+i); } } }
package Demo01_Sleep; ///1.创建一个Runnable接口的实现类 public class Demo01_Runnble implements Runnable { //在实现类中重写RunnabLe接口的run方法,设置线程任务 public static void main(String[] args) { } @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("HelloWorld"+i); } } }
匿名内部类方式实现线程的创建
使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。
使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法∶
package Demo01_Sleep; /* 匿名内部类方式实现线程的创建匿名:没有名字 内部类:写在其他类内部的类 匿名内部类作用:简化代码 把子类继承父类,重写父类的方法,创建子类对象合一步完成 把实现类实现类接口,重写接口中的方法,创建实现类对象合成—步匿名内部类的最终产物:子类/实现类对象,而这个类没有名字 格式: new父类/接口(){ 重复父类/接口中的方法 } */ public class Demo01InnerClassThread { public static void main(String[] args) { //线程的父类是Thread //new MyThread.start; new Thread(){ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+"-->"+"黑马"); } } }.start(); //线程的接口Runnable // Runnable r = neww RunnabLeImpL( );//多态 Runnable tr= new Runnable(){ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+"-->"+"程序员"); } } }; new Thread(tr).start(); //简化接口的方式 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+"-->"+"传智博客"); } } }).start(); } }