你好我是辰兮,很高興你能來閱讀,本篇爲Java基礎之多線程的實現講解,基礎知識的講解,相關的更多,面試知識已經提前整理好文章可以閱讀學習,希望對初學者有幫助。
線程進程基礎知識參考:
進程線程的面試問題小結線程面試常見問題參考:
Java常見多線程基礎面試問題
一、文章序言
創建線程的方式一致爲Java面試常見基礎問題,基礎學習中我們常用前兩種方式,下文帶大家用代碼案例進一步瞭解相關的知識。
常用第二種接口實現,因爲實現接口的方式比繼承類的方式更靈活,也能減少程序之間的耦合度。
二、繼承Thread類
繼承自Thread類,Thread類是所有線程類的父類,實現了對線程的抽取和封裝
繼承Thread類創建並啓動多線程的步驟:
- ①.定義一個類,
繼承自Thread類
,並重寫該類的run方法,該run方法的方法體就代表了線程需要完成的任務,因此,run方法的方法體被稱爲線程執行體 - ②.
創建Thread子類的對象
,即創建了子線程 - ③.用線程
對象的start方法
來啓動該線程
Demo先創建一個售票線程
package demo1;
public class SellTickets extends Thread {
//共享數據
static int count = 100;
@Override
public void run() {
//循環售票
while(count > 0) {
count--;
System.out.println(Thread.currentThread().getName() + "售出了一張票,剩餘" + count);
}
}
}
測試類
import demo1.SellTickets;
public class TheadDemo {
public static void main(String[] args) {
//模擬四個售票員售票
SellTickets s1 = new SellTickets();
SellTickets s2 = new SellTickets();
SellTickets s3 = new SellTickets();
// System.out.println(s1.currentThread().getName()); //這個線程的名稱是main
s1.start();
s2.start();
s3.start();
}
}
三、實現Runnable接口
實現Runnable接口創建並啓動多線程的步驟:
- a.
定義一個Runnable接口的實現類
,並重寫該接口中的run方法,該run方法的方法體同樣是該線程的線程執行 體 - b.
創建Runnable實現類的實例
,並以此實例作爲Thread的target來創建Thread對象,該Thread對象纔是真正的線程對象 - c.
調用線程對象的start方法
來啓動該線程
- 繼續售票的案例
應該是繼承implement接口,爲了簡潔我寫一個裏面了
package demo1;
public class SellTickets {
static int count = 100;
static Runnable r = new Runnable() {
@Override
public void run() {
while(count > 0) {
count--;
System.out.println(Thread.currentThread().getName() + "售出了 一張票,剩餘" + count);
}
}
};
public static void main(String[] args) {
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t3 = new Thread(r);
t1.start();
t2.start();
t3.start();
}
}
四、兩種實現方式的比較
①實現Runnable接口的方式
a.線程類只是實現了Runnable接口,還可以繼承其他類
【一個類在實現接口的同時還可以繼承另外一個類】
b.可以多個線程共享同一個target對象
,所以非常適合多個線程來處理同一份資源的情況
c.弊端:編程稍微複雜,不直觀,如果要訪問當前線程,必須使用Thread.currentThread()
② 繼承Thread類的方式
a.編寫簡單
,如果要訪問當前線程,除了可以通過Thread.currentThread()方式之外,還可以使用 super關鍵字
b.弊端:因爲線程類已經繼承了Thread類,則不能再繼承其他類【單繼承】
實際上大多數的多線程應用都可以採用實現Runnable接口的方式來實現【推薦使用匿名內部類】java類是單知繼承的
五、調用start()與run()方法的區別
Thread thread = new Thread();
thread.start();
① - start()方法會新建一個線程,並且讓這個線程執行run()方法。
Thread thread = new Thread();
thread.run();
② - 調用run()也能正常執行。但是,卻不能新建一個線程,而是在當前線程中調用run()方法,只是作爲一個普通的方法調用。
我知道這樣表達有點抽象,所有我截圖了上述案例
建議:不要用run()來開啓新線程,它只會在當前線程中,串行執行run()方法中的代碼。
拓展一下源碼的學習只截取了部分
public synchronized void start() {
private native void start0();
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
}
在start方法裏調用了一次start0方法,這個方法是一個只聲明未定義的方法,並且使用了native關鍵字進行定義native指的是調用本機的原生系統函數
。所以,調用start方法,會告訴JVM去分配本機系統的資源,才能實現多線程。
The best investment is to invest in yourself
2020.05.29 記錄辰兮的第70篇博客