在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);
}
}
}
实现Runnable接口 实例化Thread类
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):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。