版權聲明:本文爲博主原創文章,未經博主容許不得轉載
源碼:github.com/AnliaLee
你們要是看到有錯誤的地方或者有啥好的建議,歡迎留言評論java
這是Android多線程篇的第一章,咱們就從線程的建立聊起吧。經常使用的線程建立方式有兩種(實現Callable接口的方式,咱們放到之後介紹Executor框架的時候再敘)android
咱們本章的主題正是經過比對上述兩種方式建立的線程在執行任務時的差異,來理解Thread和Runnable的聯繫和區別git
先說結論:github
咱們就以經典的賣票系統講個故事吧。話說有小T(Thread)和小R(Runnable)兩個票販子,手下各有兩個業務員,日常就幹着倒賣活動門票的活(線程執行任務)。有一天,他們各拿到了5張某演唱會的門票,兩人將售票的任務交給手下的業務員多線程
小T這邊的業務是這樣運轉的(定義Thread類的子類,重寫run()方法,run()方法即爲賣票任務)app
public class TicketThread extends Thread {
private int ticket = 5;
private String name;
public TicketThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 5; i++) {
if (ticket > 0) {
Log.e("T公司",name + "賣了一張票,編號爲t" + (ticket--));
}
}
}
}
複製代碼
業務員一大早就開始賣票,很快就賣完了(實例化Thread的子類,調用start()方法啓動該線程)框架
TicketThread t1 = new TicketThread("1號業務員");
TicketThread t2 = new TicketThread("2號業務員");
t1.start();
t2.start();
複製代碼
而小R的業務流程則是這樣的(實現Runnable接口,重寫Runnable的run()方法)this
public class TicketRunnable implements Runnable {
private int ticket = 5;
public void run() {
for (int i = 0; i < 5; i++) {
if (ticket > 0) {
Log.e("R公司",Thread.currentThread().getName() + "賣了一張票,編號爲r" + (ticket--));
}
}
}
}
複製代碼
業務員一樣很快就把票賣完了(建立Thread子類的實例,將實現了Runnable接口的對象做爲參數實例化Thread對象,調用start()方法啓動線程)spa
TicketRunnable runnable = new TicketRunnable();
Thread r1 = new Thread(runnable, "1號業務員");
Thread r2 = new Thread(runnable, "2號業務員");
r1.start();
r2.start();
複製代碼
事畢,兩人決定吃個飯慶祝一下。一番交流後,小R很驚訝小T爲啥能夠將一樣的票多賣一倍的錢,小T得意地安利了本身的賣票心得:線程
「由於我將票複印了一份,這樣我兩個小弟就能夠各拿一份票去兜售了(經過繼承Thread的方式,當新建立一個線程啓動時,其綁定的任務一樣也新建了一份,這樣他們的任務是相互獨立的,天然也沒法實現資源共享了)」
小R聽後感嘆不已:
「居然還有這種操做?我耿直地將票交給兩個業務員就算了啊(實現Runnable接口的方式,由於都是用同一個Runnable對象建立的線程,所以多線程實際上執行的是同一個任務,這樣也就共享了資源)」
接着小R又問小T:「你這麼幹,過後不怕買到假票的人來找你?」 小T聽後不覺得然道:
「怕啥,咱們不都是幹完一票就跑路的麼(線程執行完run()方法後會自行銷燬)」
小R:「我從未見過有如此厚顏無恥之人......」
(未完待續...)
因爲小R誠信經營,生意越作越大,但最近他卻收到了一些投訴,有顧客說他們買到了假票。小R懷疑是本身手下乾的,遂決定招我的監督本身的手下。這天,一個自稱synchronized的男人前來應聘...