1 參考資料
- Java併發編程藝術第4章
- https://blog.csdn.net/Alexshi5/article/details/8804576
- https://blog.csdn.net/Alex___Zhao/article/details/75137390
- https://www.cnblogs.com/yangming1996/p/7612653.html
2 Java中線程的狀態(和OS中線程狀態對比)
首先複習下408中的操作系統的,進程和線程部分吧(唉,回憶起考研時被408支配的恐懼)
進程:計算機中資源分配的基本單位
線程:計算機中任務調度的基本單位
一個進程可以創建多個線程,多個線程共享進程的內存資源,但是,每個線程也有自己的私人空間!
線程的5中狀態:
創建,就緒,運行,阻塞,結束
創建和終止就不用說了,線程中的核心主要是另外3個狀態
Ready: 代表當前的調度實例在可執行隊列中,獲得CPU時間後就可以開始運行
**Running:**Ready獲得了CPU時間後就進入Running狀態,表示正在佔用處理器資源運行。
**Blocked:**代表當前的線程在等待相應的資源,獲得資源後可以轉變爲Ready狀態等待調度
Java中線程的6種狀態,和操作系統中的線程狀態相比,
創建狀態,終止狀態和阻塞狀態是相同的。
不同的是:
- 操作系統中的ready和running在Java線程狀態中被統一稱爲了Runnable
- Java線程狀態中多了waiting和time_waiting狀態,用於線程之間的通信(這是等待掛起 與之對應的是喚醒 notify)
6個狀態的轉換情況如下圖,
3 Java中線程的實現方式,啓動與終止
啓動
線程如何啓動–start()方法
線程如何結束–run()方法運行結束後,線程也就終止
中斷
中斷可以理解爲線程本身的一個標誌位屬性,其他線程通過調用該線程的interrpt()方法對其進行中斷操作(即 在線程A中,A去調用線程B的 B.interrupt() 方法,則B被中斷)
線程檢查自身是否被中斷,調用isInterrupt()方法判斷
如何利用中斷?
我們調用interrupt方法只是改變中斷標誌位,並沒有實際去中斷程序。要想實現中斷操作需要在程序裏手動設置檢查(這就有了很大的靈活性)
終止
- 中斷標誌
- 新建boolean變量(作用與中斷標誌位類似)
實現
如今實現Java多線程的基本方式有以下幾種
- 繼承Thread類
- 實現Runnable接口
- 實現Callable接口
- 使用ExecutorService、Callable、Future實現有返回結果的線程
以下是代碼實現:
package thread;
import java.util.concurrent.*;
public class ThreadTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// MyThread t = new MyThread("My Thread1");
// t.start();
// Thread t2 = new Thread(new MyThread2(),"MyThread2");
// t2.start();
// Callable中可以通過範型參數來指定線程的返回值類型。通過FutureTask的get方法拿到線程的返回值。
// FutureTask<Integer> futureTask = new FutureTask<>(new MyThread3());
// Thread t3 = new Thread(futureTask,"MyThread3");
// t3.start();
// System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
// Thread.sleep(1000);
// System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
//System.out.println("MyThread3 的返回值是"+futureTask.get());
//固定線程池 5
ExecutorService threadPool = Executors.newFixedThreadPool(5);
while (true){
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("當前運行的線程名爲: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
}
}
class MyThread extends Thread{
public MyThread(){
super();
}
public MyThread(String name){
super();
this.setName(name);
}
@Override
public void run() {
printThreadInfo();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printThreadInfo();
}
public void printThreadInfo(){
System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
printThreadInfo();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printThreadInfo();
}
public void printThreadInfo(){
System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
}
}
class MyThread3 implements Callable{
@Override
public Object call() throws Exception {
printThreadInfo();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printThreadInfo();
return 1;
}
public void printThreadInfo(){
System.out.println("當前線程運行名爲:"+Thread.currentThread().getName());
}
}