JUC前置知識 JUC概述 在開發語言中,線程部分是重點,JUC是關於線程的。JUC是java.util.concurrent工具包的簡稱。這是一個處理線程的工具包,JDK1.5開始出現的。 線程和進程 線程和進程的概念 進程(process): 是電腦的程式關於某數據集合上的一次允許活動,是操作 ...
JUC前置知識
JUC概述
在開發語言中,線程部分是重點,JUC是關於線程的。JUC是java.util.concurrent工具包的簡稱。這是一個處理線程的工具包,JDK1.5開始出現的。
線程和進程
線程和進程的概念
進程(process): 是電腦的程式關於某數據集合上的一次允許活動,是操作系統進行資源分配和任務調度的最小單位,是操作系統的基礎。在當代面向線程設計的電腦結構中,進程是線程的容器。程式是指令,數據及其組織形式的描述,進程是程式的實體。
線程(thread): 是操作系統或CPU核心能夠進行調度的最小單位。被包含在進程中,是進程中的實際運行單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以有多個線程,每個線程執行不同的任務。
總結
進程,是在系統中正在運行的一個應用程式,程式一旦運行就是進程,也是操作系統資源分配的最小單位。
線程,是CPU(Central Processing Unit縮寫)核心(現代電腦的CPU可以有多個CPU核心,俗稱的4核,8核等)進行資源調度的最小單位,或者說進程內獨立執行的一個執行流單元,也是程式執行的最小單位。
線程的狀態
線程狀態類
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
//新建
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
//準備就緒,可以運行
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
//阻塞
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
//等待,不見不散
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
//定時等待,過時不候
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
//停止,終止
TERMINATED;
}
wait和sleep方法的區別
- 1.sleep是Thread類的靜態方法,wait是Object類的方法,任何對象實例都能調用。
- 2.sleep不會釋放鎖,也不需要占有鎖。wait會釋放鎖,但釋放鎖這個動作的前提是,當前線程占有鎖。
- 3.這兩個方法都可以被interrupted方法中斷。
- 4.這兩個方法還有個特點,就是線程在哪裡被阻塞,就在哪裡被喚醒。
串列,並行和併發
串列模式
串列表示所有任務一一按先後順序進行。串列意味著必須先裝完一車柴才能運送這車柴,只有運送到了,才能卸下這車柴,並且只有完成了這三個步驟,才能進行下一步驟。串列是一次只能取得一個任務,並執行這個任務。
並行模式
並行意味著可以同時取得多個任務,,並同時去執行所取得的這些任務。並行模式相當於將長長的一條隊列,劃分成了多條短隊列,所以並行縮短了任務隊列的長度。並行的效率從代碼層次上,強依賴於多進程/多線程代碼,從硬體角度上依賴於多核CPU。
併發
指的是多個程式可以同時運行的現象,更細化的是多進程可以同時運行或者多指令可以同時運行。
併發的重點是一種現象,描述的是多進程同時運行的現象。但實際上,一個CPU同時,只能運行一個線程。所以同時運行,不是同一時刻有多個線程運行的現象,而是提供一種功能,讓用戶看起來多個程式同時運行了,但是實際上的線程不是一直霸占CPU的,而是執行一會停,一會執行。
要解決大併發問題,通常是將大任務分解成多個小任務,由於OS(Operating System)對進程的調度是隨機的,所以切分成多個小任務後,可能會從任一小任務出執行。可能出現的問題,一個小任務執行了多次,還沒開始下個任務。這時一般會採用隊列或類似數據結構來存放各個小任務的成果。可能出現還沒準備好第一步,就執行第二步的可能。這時,一般採用多路復用或非同步的方式,比如只有準備好了,才產生事件執行下一步任務。可以多進程/多線程的方式並行執行這些小任務。也可以單進程/單線程執行這些小任務,這是很可能要配合多路復用才能達到較高的效率。
小結
併發:同一時刻多個線程在訪問同一資源,多個線程對一個點。如春運搶票,電商秒殺。
並行:多項工作一起執行,之後再彙總。如泡泡麵,水壺燒水,一邊放調料。
管程
管程又叫Monitor(監視器),在OS中叫管程/Monitor(監視器),在Java中叫鎖(Lock)。
鎖其實是一種同步機制,保證同一時間內,只能有一個線程訪問受保護的資源。
在JVM中實現這個鎖機制(同步機制),是通過進入,退出管程對象實現的,也就是常說的持有鎖,和釋放鎖。進入管程(擁有鎖),退出管程(釋放鎖)。一個線程持有該鎖,就只有當前線程可以訪問,該鎖保護的資源。釋放鎖,就是當前線程不訪問,該鎖保護的資源了,其他線程可以競爭該鎖,誰獲取到鎖,可以訪問鎖保護的線程。
用戶線程和守護線程
daemon n.守護神
用戶線程和守護線程,是jvm中的概念。
用戶線程,顧名思義,用戶自定義的線程。主線程結束,用戶線程還在運行,jvm存活。
守護線程 ,用於守護用戶線程,執行的線程如垃圾回收(gc)。沒有用戶線程,都是守護線程的化話,主線程結束,jvm結束。設置一個線程為守護線程,必須在開啟這個線程之前。
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isDaemon());// aa true
while(true){
}
},"aa");
thread.setDaemon(true);//通過該方法可將線程設置為守護線程
thread.start();
System.out.println(Thread.currentThread().getName() + "over");// mainover
}
}
只是為了記錄自己的學習歷程,且本人水平有限,不對之處,請指正。