JAVA基礎22-多執行緒(一)【多執行緒的概念,執行緒狀態及其轉換】
多執行緒
一.概念
1. 程序:程序是表示資源分配的的基本概念,又是排程執行的基本單位,是系統中的併發執行的單位。
2. 執行緒:單個程序中執行中每個任務就是一個執行緒。執行緒是程序中執行運算的最小單位。且執行緒只能屬於一個執行緒。
3.執行緒是一種輕量級的程序。
4.執行緒沒有地址空間,執行緒包含在程序的地址空間中。
5.多執行緒三大特性: 原子性,可見性,有序性。
二. Java執行緒具有的5種狀態
新建狀態(NEW):當執行緒物件被建立後,即進入新建狀態。【Thread t=new Thread()】
就緒狀態(Runable):當執行緒物件呼叫了start方法,即進入就緒狀態,等待cpu排程執行【t.start()】
執行狀態(Running) :就緒狀態的執行緒,被cpu排程即,進入執行狀態
阻塞狀態(Blocked):處於執行狀態中的執行緒由於某種原因,暫時放棄對CPU的使用權,停止執行,此時執行緒進入阻塞狀態;
三種阻塞狀態
A.等待阻塞;執行狀態中執行緒執行了wait()方法,使得本執行緒進入阻塞狀態
B.同步阻塞;執行緒在獲取synchronized同步鎖(鎖被其他執行緒鎖佔有),進入同步阻塞狀態
C.其他阻塞:執行緒呼叫了sleep(),join()或者發出I/O請求時,執行緒會進入阻塞狀態,當sleep超時,join等待執行緒終止或者超時,I/O請求完成,執行緒會進入就緒狀態
死亡狀態(Dead): 執行緒執行完了,或者因異常退出run()方法。
三.執行緒屬性
1.執行緒優先順序
執行緒範圍:0-10;預設優先順序為5;高優先順序的執行緒先執行。
預設情況下,執行緒是繼承父類的優先順序;也可通過setPriority()修改優先順序。
2.使用者執行緒和守護執行緒
使用者執行緒:非守護執行緒,常規的執行緒
守護執行緒:作用是為其他執行緒提供服務。只要當JVM還有使用者執行緒,那麼守護執行緒就會一直工作下去。例如:垃圾回收期;
程式編寫者可以設定守護執行緒;方法: t.setDaemon(true)
四.執行緒建立(NEW和Runable狀態)
1.繼承Thread類,重寫run()方法
package com.demo9aa.demo7;
public class ThreadA extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
int i =0;
for(;i<10;i++){
System.out.println(i);
}
}
public static void main(String[] args) {
ThreadA a=new ThreadA();//建立ThreadA;new狀態
a.start();//runable狀態
}
}
2.實現Runable介面,並重寫該介面的run()方法
package com.demo9aa.demo7;
public class ThreadB implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
int i=0;
for(;i<10;i++){
System.out.println(i);
}
}
}
3.使用Callable和Future介面建立執行緒。
A.建立Callable介面的實現類,並實現call()方法。
B.使用FutureTask類來包裝Callable實現類的物件,
C.此FutureTask物件作為Thread物件的target來建立執行緒。
package com.demo9aa.demo7;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Demo1 {
public static void main(String[] args) {
//A
Callable<Integer> c=new CallAbleA();
//B
FutureTask<Integer> f=new FutureTask<>(c);
//C
Thread r=new Thread(f);
r.start();
}
}
class CallAbleA implements Callable<Integer>{
int i=0;
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
for(;i<10;i++){
System.out.println(i);
}
return i;
}
}
五.執行緒讓步(yield方法)
從執行態轉換為就緒態有兩種情況 1.時間片用完。2.執行緒主動呼叫yield()
yield方法作用:主動歸還資源,使自己在就緒態
六.其他阻塞(I/O請求,sleep,join)
I/O請求:當執行緒開始進行I/O操作時,執行緒進入阻塞狀態。I/O操作完成後,執行緒進入就緒態
join函式: 讓一個執行緒等待另一個執行緒完成,才可以繼續執行【在子執行緒未完成或者未超時之間,父執行緒進入阻塞狀態;子執行緒完成或者超時,父執行緒進入就緒態】
sleep函式:讓當前正在執行的執行緒,暫停製定時間,並進入阻塞狀態【在睡眠時間,執行緒進入阻塞狀態,超時後,恢復到就緒態】
七.等待阻塞和同步阻塞
A:等待阻塞
當正在執行時的執行緒(已獲得鎖),呼叫wait()方法時,執行緒主動放棄鎖,此時執行緒進入 等待阻塞狀態。
B: 同步阻塞
當正在執行的執行緒(未獲得鎖),獲得鎖失敗(鎖被其他執行緒鎖佔用),執行緒進入同步阻塞階段。
當執行執行緒,呼叫notify和notifyAll方法;此時喚醒“等待阻塞的執行緒“進入同步阻塞階段。
同步阻塞的執行緒,一旦獲得鎖,就進入就緒態。
八.執行緒中斷
8-1.歷史方法: Thread有成員方法:suspend和stop都用於中斷執行緒。 問題? ?? 執行緒強制中斷,會導致鎖永遠無法歸還。
8-2.最新做法: 使用等待/通知或者給哪個執行緒一箇中斷訊號,讓他自己決定中斷。
8-2-1.涉及方法:
interrupted()方法: 靜態方法;檢視當前中斷訊號,並其清除中斷訊號
isInterrupted()方法: 檢視當前中斷訊號。
interrupt()方法:修改被呼叫執行緒的中斷狀態,告知那個執行緒,他需要被中斷。
8-2-2.詳細操作如下:
對於非阻塞執行緒:修改了中斷狀態【Thread.isInterrupted返回true】,無任何特殊現象
對於可取消的阻塞狀態的執行緒中:(wait,sleep,join)
A 執行緒收到中斷訊號後,會丟擲InterruptedException;
B 丟擲異常後會把中斷狀態置為true
對於不可中斷阻塞的執行緒中:(I/O請求時):
執行緒收到中斷資訊後,,他們不會丟擲InterruptedException,且不會因為中斷情況,而退出阻塞。
注意:
嘗試獲取一個內部鎖的操作(進入一個 synchronized 塊)是不能被中斷的; 但是 ReentrantLock 支援可中斷的獲取模式即 tryLock(long time, TimeUnit unit)。