Java線程類有兩種實(shí)現(xiàn)方式,第一種就是繼承Thread類,另一種是現(xiàn)實(shí)Runnable接口。這兩種實(shí)現(xiàn)方式的區(qū)別很大,下面就說一下它們之間到底有什么區(qū)別。
我們首先用第一種方式寫一個(gè)線程類:
代碼如下:
package Ticket;
public class Extends {
public static void main(String[] args){
//實(shí)例化進(jìn)程并準(zhǔn)備執(zhí)行
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
}
}
class MyThread extends Thread{
//定義一個(gè)變量
private int ticket = 10;
public void run(){
//這里之所以要循環(huán)300次,就是為了讓所有的 車票都賣出去!可能你會(huì)想,為什么不是30呢?
//嘿嘿。。。聰明的你肯定明白這個(gè)循環(huán)的次數(shù)為什么會(huì)多出票數(shù)很多?=====其實(shí)我開始也不知道!!! ==|||
for(int i=0;i<300;i++){
try {
//調(diào)用sell()方法
this.sell();
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sell(){
if(ticket>0){
System.out.println(Thread.currentThread().getName() + " ===> 還剩下" + (ticket--) + "車票");
}
}
}
看看這個(gè)程序的運(yùn)行結(jié)果你就明白為什么繼承Thread類實(shí)現(xiàn)線程類的一個(gè)弊端

------------------------------------------------
大家都發(fā)現(xiàn)了吧!輸出的結(jié)果和預(yù)想的不一樣!!!
我們來分析一下代碼,查看main函數(shù):
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
new Thread(new MyThread(),"001窗口").start();
我們可以看出,實(shí)例化了三個(gè)MyThread類,這樣的話,private int ticket = 10;就運(yùn)行了三次,所以ticket打印出來的 也就是30張;在這里注意一下并不是ticket賦值為30,而是ticket賦值為10,但賦值了三次!!!也就是現(xiàn)在有三個(gè)ticket!!!
這樣并不能實(shí)現(xiàn)資源共享!
我們知道我們利用多線程就是為了將多個(gè)線程去處理一個(gè)數(shù)據(jù)的集合!!! 他們是同時(shí)處理的!!!如果向上面的話,并沒有將數(shù)據(jù)的集合(ticket)進(jìn)行共享,而是將每一個(gè)類都從新建了一個(gè)數(shù)據(jù)的集合,分別對自己的集合進(jìn)行處理!!!!
如果想解決這個(gè)問題,其實(shí)也很簡單,不過如果當(dāng)數(shù)據(jù)的類型和種類比較多的時(shí)候,這樣寫就太麻煩了!!!!
那實(shí)現(xiàn)Runnable接口的線程類可不可以呢!!???
下面來看一看:
代碼如下:
package IO;
public class Inter {
public static void main(String[] args){
//聲明并實(shí)例化一個(gè)MyThread01類
MyThread01 mt = new MyThread01();
new Thread(mt,"001窗口").start();
new Thread(mt,"002窗口").start();
new Thread(mt,"003窗口").start();
}
}
class MyThread01 implements Runnable{
private int ticket = 10;
public void run(){
for(int i=0;i<200;i++){
try {
this.sell();
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sell(){
if(ticket>0){
System.out.println(Thread.currentThread().getName() + " ===> 還剩下" + (ticket--) + "車票");
}
}
}
---------------------------------------------
這段程序的運(yùn)行結(jié)果:

看看這個(gè)結(jié)果是不是和自己想的一樣啊!!!這樣就可以了!!!用這個(gè)方法去創(chuàng)建一個(gè)線程類是不是可以達(dá)到資源共享啊!!!
其實(shí)啊!我看來,所謂的資源共享也就是將一個(gè)數(shù)據(jù)的集合讓多個(gè)線程去處理!!!
我們看一下代碼!!!
MyThread01 mt = new MyThread01();
new Thread(mt,"001窗口").start();
new Thread(mt,"002窗口").start();
new Thread(mt,"003窗口").start();
我們可以看出這個(gè)過程中,我們只聲明并實(shí)例化了一個(gè)MyThread01類,也就是說在這里過程中,給ticket進(jìn)行了初始化!!!
但大家要注意的是:真正創(chuàng)建處理數(shù)據(jù)的線程是
new Thread(mt,"001窗口").start();
new Thread(mt,"002窗口").start();
new Thread(mt,"003窗口").start();
因此,這樣可以將一個(gè)ticket的數(shù)據(jù)集 由三個(gè)線程來處理!!!
這樣就是所謂的資源共享!!!
ok???
=====================================================================
總結(jié)一下這兩種方式的特點(diǎn):
1.繼承Thread來創(chuàng)建線程類的方法,在繼承了Thread后,不能再繼承其他類,這樣靈活性就不如實(shí)現(xiàn)Runnable接口來創(chuàng)建線程類的方法了!!!
2.正如上面所說的使用實(shí)現(xiàn)Runnable接口來創(chuàng)建線程類的方法可以達(dá)到資源共享!!!(在這里說明一下:繼承Thread類來創(chuàng)建線程類的方法也可以實(shí)現(xiàn)資源共享,只不過比較麻煩!!!因此,在創(chuàng)建線程類的時(shí)候,應(yīng)優(yōu)先選擇實(shí)現(xiàn)Runnable接口來創(chuàng)建線程類的方法!!!)