Java多线程的使用
無論在我們的工作中還是在我們的生活中,我們都會用到多線程的知識,今天就給大家講一下如何使用多線程。
序幕
線程的啟動
如何使線程暫停
如何使線程停止
線程的優先級
線程安全相關的問題
我們首先要知道進程和線程分別是什么?
進程 - 進程是具有一定獨立功能的程序(例如QQ.exe),關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。
線程 - 線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位;線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以并發執行。
相對進程而言,線程是一個更加接近于執行體的概念,它可以與同進程中的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
在串行程序基礎上引入線程和進程是為了提高程序的并發度,從而提高程序運行效率和響應時間。
多線程的優點
多線程從某方面來說等價于多任務,當你有多個任務要處理時,多個任務一起做所消耗的時間肯定比任務串行起來做,所消耗的時間短;
如圖所示
多線程的使用
在Java的JDK包中,已經自帶了對多線程技術的支持,可以非常方便地進行多線程的編程。實現多線程編程的方式主要有兩種:
繼承Thread類
實現Runnable接口
如圖所示
Thread類實現了Runnable接口,它們之間具有多態關系。
Runnable接口類
@FunctionalInterface public interface Runnable {public abstract void run(); }Thread類主要源碼:
public class Thread implements Runnable {public static native Thread currentThread();public static native void yield();public static native void sleep(long millis) throws InterruptedException;public static void sleep(long millis, int nanos) throws InterruptedException {// ...sleep(millis);}public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}public Thread(ThreadGroup group, Runnable target) {init(group, target, "Thread-" + nextThreadNum(), 0);}public synchronized void start() {// ...start0(); // ...}private native void start0();@Deprecatedpublic final void stop() {// ...}public void interrupt() {// ...}public static boolean interrupted() {return currentThread().isInterrupted(true);}public boolean isInterrupted() {return isInterrupted(false);}private native boolean isInterrupted(boolean ClearInterrupted);public final native boolean isAlive();@Deprecatedpublic final void suspend() {checkAccess();suspend0();}@Deprecatedpublic final void resume() {checkAccess();resume0();} }這二種創建線程的方式有什么區別?
Java類是單繼承的,而接口可以支持多繼承,使用Thread類的方式創建新線程時,最大的局限就是不支持多繼承。所以具體選擇哪種方式來創建線程,就看你是不是需要具體多繼承的特性。
Thread詳解
看到Thread的源碼,我們現在對其主要的的一些方法進行講解一下
native關鍵字 - native是與C++聯合開發的時候用的!使用native關鍵字說明這個方法是原生函數,也就是說這個方法是用C/C++語言實現的,并且被編譯成dll相關組件,由java來調用。所以從上面的Thread類源代碼中可以看到,有好多是調用了原生的函數。
構造方法 - Thread有一組構造方法,具體指定了線程名稱(name)、線程組(ThreadGroup)、接口類(Runnable)、棧大小(stackSize)等參數 具體如下:
public Thread() public Thread(Runnable target) Thread(Runnable target, AccessControlContext acc) public Thread(ThreadGroup group, Runnable target) public Thread(String name) public Thread(ThreadGroup group, String name) public Thread(Runnable target, String name) public Thread(ThreadGroup group, Runnable target, String name) public Thread(ThreadGroup group, Runnable target, String name, long stackSize)isAlive() - 方法isAlive()是判斷當前的線程是否處于活動狀態。而這個活動狀態指的是:線程已經啟動且尚未終止,如正在運行,準備開始運行的狀態,都認為線程是“存活”的。
sleep() - 在指定的毫秒數內讓當前“正在執行的線程”休眠(暫停執行)。這個“正在執行的線程”是指this.currentThread()返回的線程。
getId() - 取得線程的唯一標識。每個線程在初始化的過程中都會調用nextThreadID方法獲取到一個唯一標識。
private static long threadSeqNumber; private static synchronized long nextThreadID() {return ++threadSeqNumber; }在一個進程中,線程的ID是唯一。
停止線程 - 停止線程是在多線程開始時很重要的技術點,而停止線程在Java中并不像break語句那樣干脆,需要一些技巧性的處理。
在Java中有以下3種方法可以終止正在運行的線程。
1.使用退出標志,使線程正常退出,即當run方法完成后線程終止。
2.使用stop方法強行終止線程,但是不推薦使用該方法,因為stop和suspend及resume一樣,都是作廢過期的方法,使用它們可能產生不可預料的結果。
3.使用interrupt方法中斷線程。
暫停線程 - 暫停線程意味著此線程還可以恢復運行。使用suspend()方法暫停線程,resume()方法恢復線程的執行。
yield - yield()方法的作用是放棄當前的CPU資源,將它讓給其他的任務去占用CPU執行時間。但是放棄的時間不確定,有可能剛放棄,馬上又獲得CPU時間片了。
線程優先級 - 在操作系統中,線程可以劃分優先級,優先級較高的線程得到的CPU資料較多,也就是CPU優先執行優先級較高的線程對象中的任務。在Thread中,我們使用setPriority()方法設置優先級別。
java的線程優先級分為1~10這10個等級
public final static int MIN_PRIORITY = 1; public final static int NORM_PRIORITY = 5; public final static int MAX_PRIORITY = 10;線程優先級的三個特性
線程優先級具有繼承特性, 比如A線程啟動B線程,則B線程的優先級與A是一樣的。
優先級具有規則性,雖然我們使用setPriority()方法設置了優先級,但是真正執行的過程中,不會保證優先級高的線程絕對比優先級低的線程優先完成。即CPU盡量將執行資源讓給優先級比較高的線程。
*優先級具有隨機性,具優先級較高的線程不一定每一次都先執行完。
守護線程 - 在Java線程中有兩種線程,一種是用戶線程,另一種是守護線程。
守護線程是一種特殊的線程,它的特性有“陪伴”的含義,當進程中不存在非守護線程了,則守護線程自動銷毀。
典型的守護線程就是垃圾回收線程,當進程中沒有非守護線程了,則垃圾回收線程則沒有存在的必要了,自動銷毀。
只要當前JVM實例中存在任何一個非守護線程沒有結束,守護線程就在工作,只有當最后一個非守護線程結束時,守護線程才隨著JVM一同結束工作。
通過調用Thread.setDaemon(true)設置是否為守護線程。
總結
以上是生活随笔為你收集整理的Java多线程的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring基于Annotation实现
- 下一篇: Java多态性