在java中要想实现多线程,有两种手段,一种是继承Thread类,另外一种是实现Runnable接口
继承Thread类
public class lzwCode extends Thread{ public static void main(String [] args) { new Thread(new lzwCode(), "线程名字").start(); } public void run() { for (int i=0; i<5; i++) { System.out.println(Thread.currentThread().getName()+ " "+i); } } }
public class lzwCode implements Runnable{ public static void main(String [] args) { new Thread(new lzwCode(), "线程名字").start(); } public void run() { for (int i=0; i<5; i++) { System.out.println(Thread.currentThread().getName()+ " "+i); } } }
其实Thread中的run方法调用的是Runnable接口的run方法。其实Thread和Runnable都实现了run()方法,这种操作模式其实就是代理模式
查看start的源代码的时候,会发现,此处调用的是start0()。并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } private native void start0();
两者结果都一样:
Thread和Runnable的区别:
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
在实际应用中,我们经常用到多线程,如车站的售票系统(总共5张票 O(∩_∩)O),车站的各个售票口相当于各个线程。当我们做这个系统的时候可能会想到两种方式来实现,继承Thread类或实现Runnable接口,现在看一下这两种方式实现的两种结果。
class MyThread extends Thread{ private int ticket = 5; //5张票 private String name; public MyThread(String name) { this.name = name; } public void run() { for (int i=0; i<=20; i++) { if (this.ticket > 0) { System.out.println(this.name+ "正在卖票"+this.ticket--); } } } } public class lzwCode { public static void main(String [] args) { MyThread myA = new MyThread("1号窗口"); MyThread myB = new MyThread("2号窗口"); MyThread myC = new MyThread("3号窗口"); myA.start(); myB.start(); myC.start(); } }
大家可以想象,如果这个是一个买票系统的话,说明并没有实现资源的共享。
class MyThread implements Runnable{ private int ticket = 5; //5张票 public void run() { for (int i=0; i<=20; i++) { if (this.ticket > 0) { System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--); } } } } public class lzwCode { public static void main(String [] args) { MyThread my = new MyThread(); new Thread(my, "1号窗口").start(); new Thread(my, "2号窗口").start(); new Thread(my, "3号窗口").start(); } }
为什么会出现这种结果呐。我们不妨做个比喻,其实刚的程序,继承Thread类的,我们相当于拿出三件事即三个卖票5张的任务分别分给三个窗口,他们各做各的事各卖各的票各完成各的任务,因为MyThread继承Thread类,所以在new MyThread的时候在创建三个对象的同时创建了三个线程;实现Runnable的, 相当于是拿出一个卖票5张得任务给三个人去共同完成,new MyThread相当于创建一个任务,然后实例化三个Thread,创建三个线程即安排三个窗口去执行。
实现Runnable接口比继承Thread类所具有的优势(建议大家劲量实现接口):
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。