java线程实现方式:Runnable和Thread的区别

时间:2022-04-14 17:34:11
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;
Thread是java.lang包中类,Runnable是java.lang包中的接口。
方法一:继承Thread类
package com.hundsun.test;
public class MyThread extends Thread{
private String name;  //线程名称
public MyThread(String name) {
super();
this.name=name;
}
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("线程开始:"+this.name+",i="+i);
}
}

public static void main(String[] args) {
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
mt1.start();
mt2.start();
//mt1.run();
//mt2.run();   //直接调用run()方法实现不了多线程
}


}


方法二:实现Runnable接口
package com.hundsun.runnable;
public class MyThread implements Runnable{
private String name;  //线程名称
public MyThread(String name){
this.name=name;
}
public void run() {
for(int i=0;i<10;i++){
System.out.println("线程开始:"+this.name+",i="+i);

}
}
public static void main(String[] args) {
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
//mt1.run();    //直接调用run()方法实现不了多线程,需要通过Thread类来启动
//mt2.run();
new Thread(mt1).start();
new Thread(mt2).start();
}
}


两种实现方法的区别:
两种方法都需要实现run()方法,都需要通过Thread类的start()方法类启动多线程;
但是实现Runnable接口比继承Thread类的好处是可以避免继承局限,一个类只能有一个
父类但是可以继承多个接口。


那么为啥非要使用start()方法启动多线程呢?
在JDK的安装路径下,src.zip是全部的java源程序,
通过此代码找到Thread中的start()方法的定义,
可以发现此方法中使用了private native void start0();
其中native关键字表示可以调用操作系统的底层函数,
那么这样的技术成为JNI技术(java Native Interface)




下面分别继承Thread类和实现Runnabale接口实现模拟卖票的程序:
方法一:继承Thread类
package com.hundsun.test;
public class MultiTickets extends Thread{
private String name;
    private int tickets=100;
public MultiTickets(String name){
this.name=name;
}
@Override
public synchronized void run() {
for(int i=1;i<=100;i++){
if(this.tickets > 0)
{
System.out.println(this.name+":卖出票号 "+i);
this.tickets--;
}
}
}
public static void main(String[] args) {
/*
下面这段代码是错误的实现方式,因为分别new了三个类,达不到资源共享,
每个线程都会卖出100张票
如果把修改tictets为静态变量(static private int tickets=100),这样
线程之间就无法同步,因为分别属于三个对象
*/
/*MultiTickets mt1=new MultiTickets("线程A");
MultiTickets mt2=new MultiTickets("线程B");
MultiTickets mt3=new MultiTickets("线程C");
mt1.start();
mt2.start();
mt3.start();
*/
MultiTickets mt=new MultiTickets("卖票线程");
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
}
}




方法二:实现Runnable接口
package com.hundsun.test;
public class MultiTickets2 implements Runnable{
private String name;
private int tickets=100;
public MultiTickets2(String name){
this.name=name;
}
public synchronized void run() {
for(int i=1;i<=100;i++){
if(this.tickets > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.name+":卖出票号 "+i);
this.tickets--;
}
}

}

public static void main(String[] args) {
MultiTickets2 mt=new MultiTickets2("卖票线程");
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();

}
}