一、創建多執行緒的兩種方式
1.繼承Thread類,重寫run方法
2.實作Runnable介面,重寫run方法
3.直接上代碼
package com.ruigege.threadFoundation1;
public class MyThreadExtendsType extends Thread {
@Override
public void run() {
System.out.println("這是一個繼承Thread類的多執行緒表示方法");
}
}
package com.ruigege.threadFoundation1;
public class MyThreadImplementsRunnable implements Runnable{
@Override
public void run() {
System.out.println("這是一個實作Runable介面的多執行緒");
}
}
package com.ruigege.threadFoundation1;
public class MultiBuildThreadTest {
public static void main(String[] args) {
//使用繼承Thread的類的方式來進行多執行緒創建
MyThreadExtendsType thread1 = new MyThreadExtendsType();
thread1.start();
//使用實作Runnable介面的方式進行多執行緒創建
Thread thread2 = new Thread(new MyThreadImplementsRunnable());
thread2.start();
}
}
4.二者之間的差別
- (1)呼叫方式:繼承的時候直接創建新的實體,然后呼叫run方法;實作介面的方式,要創建一個實體作為引數作為Thread的構造方法中,再進行呼叫
- (2)擴展性:繼承只能單繼承,耦合度高;實作的方式就不一樣了,耦合度小
- (3)繼承的好處,就是在實體中直接使用this關鍵字就可以使用該執行緒,而不需要呼叫Thread.currendThread()方法來獲取實體,可以在子類中添加成員變數,如果使用了Runnable方式,那么只能使用主執行緒中被宣告為final的變數
- (4)兩種方式都有一個弊端,就是沒有回傳值,下面再介紹一種
5.第三中方式,使用FuntureTask
package com.ruigege.threadFoundation1;
import java.util.concurrent.Callable;
public class MyThreadImplementsCallable implements Callable<String> {
@Override
public String call() throws Exception{
System.out.println("使用FutureTask的方式來行創建多執行緒");
return "創建好了";
}
}
package com.ruigege.threadFoundation1;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MultiBuildThreadTest {
public static void main(String[] args) throws InterruptedException, ExecutionException{
//使用Callable和FutureTask來創建多執行緒
FutureTask<String> futurnTask = new FutureTask<>(new MyThreadImplementsCallable());
Thread thread3 = new Thread(futurnTask);
thread3.start();
System.out.println(futurnTask.get());
}
}

6.知識掃盲
- 系統進行資源調度和記憶體分配的基本單位------行程
- 執行緒就是行程的一個執行路徑
- 內部的機制:一個行程中有一個或者多個執行緒,行程中的堆和方法區執行緒內公用,執行緒中的堆疊和程式計數器,自己獨有,

- 程式計數器是用于記錄執行緒當前要執行的地址(原理:CPU是分片加載執行的,一片執行完,要記住下一次從哪里執行)
執行native方法,pc計數器是undefined地址;執行Java代碼的時候才是原定義
- 堆是什么時候分配的?行程創建的時候就會分配一塊記憶體區域給堆,
- 就緒狀態:呼叫了start()方法之后,并沒有馬上執行執行緒,這個就緒狀態就是獲取了除了CPU以外的所有的資源的狀態,一旦獲取了CPU資源后,才會開始真正執行,
二、native關鍵字
- JNI(Java Native Inteface)
- 作用:使用在方法名稱的前面,意味著這個方法,并不是使用Java來撰寫,而是由其他語言來撰寫的,這個native就是宣告這是個原生函式,具體是由C/C++來實作的并且會編譯成dll檔案,供Java來進行呼叫
- 使用這種機制的原因:Java并非完美,在一些要求高性能的場景中,往往C/C++語言會更加快,于是native的出現能夠很好的解決這個問題,
- 實作的步驟:(1)首先使用native關鍵字來宣告這個方法是原生方法;
(2)使用Javah生成一個類似于頭檔案的檔案;(3)使用C/C++來撰寫這個函式,注意其中要參考第二步中產生的頭檔案(這個頭檔案又參考了jni.h這個頭檔案);(4)將這個寫好的C碼編譯成一個元件檔案;
(5)在Java程式中使用System.loadLibrary()來加載這個元件檔案,

三、如果獲取共享變數的監視器鎖
- 使用這個共享變數的時候,用synchronized關鍵字進行同步代碼塊
synchronized(共享變數){
}
- 該共享變數在方法中的引數的時候
synchronzied void add (int a,int b){
a + b;
}
四、虛假喚醒
- 一個執行緒的共享變數通過呼叫自身的wait()方法來進入阻塞狀態,那如果想要從掛起狀態恢復到運行狀態,那么只有三種方式:(1)其他執行緒呼叫了該物件notify()或者notifyAll()方法的時候;(2)其他執行緒呼叫了該物件的interrupt()方法;
- 如果沒有以上兩種情況,或者等待超時,仍然恢復運行狀態就叫虛假喚醒
- 避免這種情況的方式
synchronize(obj){
while(條件不滿足){
obj.wait();
}
}
- 退出回圈的條件就是滿足了喚醒該執行緒的條件,
五、原始碼:
https://github.com/ruigege66/ConcurrentJava- CSDN:https://blog.csdn.net/weixin_44630050
- 博客園:https://www.cnblogs.com/ruigege0000/
- 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/191121.html
標籤:Java
