国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

java并發(fā)編程:多線程基礎(chǔ)知識介紹

這篇具有很好參考價值的文章主要介紹了java并發(fā)編程:多線程基礎(chǔ)知識介紹。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


進程與線程

最初的計算機只能接受一些特定的指令,用戶每輸入一個指令,計算機就做出一個操作。當用戶在思考或者輸入時,計算機就在等待。這樣效率非常低下,在很多時候,計算機都處在等待狀態(tài)。

后來有了批處理操作系統(tǒng),把一系列需要操作的指令寫下來,形成一個清單,一次性交給計算機。用戶將多個需要執(zhí)行的程序?qū)懺诖艓希缓蠼挥捎嬎銠C去讀取并逐個執(zhí)行這些程序,并將輸出結(jié)果寫在另一個磁帶上。

批處理操作系統(tǒng)在一定程度上提高了計算機的效率,但是由于批處理操作系統(tǒng)的指令運行方式仍然是串行的,內(nèi)存中始終只有一個程序在運行,后面的程序需要等待前面的程序執(zhí)行完成后才能開始執(zhí)行,而前面的程序有時會由于I/O操作、網(wǎng)絡(luò)等原因阻塞,所以批處理操作效率也不高。

人們對于計算機的性能要求越來越高,現(xiàn)有的批處理操作系統(tǒng)并不能滿足人們的需求,而批處理操作系統(tǒng)的瓶頸在于內(nèi)存中只存在一個程序,那么內(nèi)存中能不能存在多個程序呢?這是人們亟待解決的問題。

于是,科學(xué)家們提出了進程的概念。

進程就是應(yīng)用程序在內(nèi)存中分配的空間,也就是正在運行的程序,各個進程之間互不干擾。同時進程保存著程序每一個時刻運行的狀態(tài)。

此時,CPU采用時間片輪轉(zhuǎn)的方式運行進程:CPU為每個進程分配一個時間段,稱作它的時間片。如果在時間片結(jié)束時進程還在運行,則暫停這個進程的運行,并且CPU分配給另一個進程(這個過程叫做上下文切換)。如果進程在時間片結(jié)束前阻塞或結(jié)束,則CPU立即進行切換,不用等待時間片用完。

當進程暫停時,它會保存當前進程的狀態(tài)(進程標識,進程使用的資源等),在下一次切換回來時根據(jù)之前保存的狀態(tài)進行恢復(fù),接著繼續(xù)執(zhí)行。

使用進程+CPU時間片輪轉(zhuǎn)方式的操作系統(tǒng),在宏觀上看起來同一時間段執(zhí)行多個任務(wù),換句話說,進程讓操作系統(tǒng)的并發(fā)成為了可能。雖然并發(fā)從宏觀上看有多個任務(wù)在執(zhí)行,但在事實上,對于單核CPU來說,任意具體時刻都只有一個任務(wù)在占用CPU資源。

雖然進程的出現(xiàn),使得操作系統(tǒng)的性能大大提升,但是隨著時間的推移,人們并不滿足一個進程在一段時間只能做一件事情,如果一個進程有多個子任務(wù)時,只能逐個得執(zhí)行這些子任務(wù),很影響效率。

那么能不能讓這些子任務(wù)同時執(zhí)行呢?于是人們又提出了線程的概念,讓一個線程執(zhí)行一個子任務(wù),這樣一個進程就包含了多個線程,每個線程負責一個單獨的子任務(wù)。

總之,進程和線程的提出極大的提高了操作系統(tǒng)的性能。進程讓操作系統(tǒng)的并發(fā)性成為了可能,而線程讓進程的內(nèi)部并發(fā)成為了可能。

多進程方式確實可以實現(xiàn)并發(fā),但使用多線程,有以下幾個好處:

  • 進程間的通信比較復(fù)雜,而線程間的通信比較簡單,通常情況下,我們需要使用共享資源,這些資源在線程間的通信比較容易。
  • 進程是重量級的,而線程是輕量級的,故多線程方式的系統(tǒng)開銷更小。

進程和線程的區(qū)別

進程是一個獨立的運行環(huán)境,而線程是在進程中執(zhí)行的一個任務(wù)。

他們兩個本質(zhì)的區(qū)別是是否單獨占有內(nèi)存地址空間及其它系統(tǒng)資源(比如I/O)

  • 進程單獨占有一定的內(nèi)存地址空間,所以進程間存在內(nèi)存隔離,數(shù)據(jù)是分開的,數(shù)據(jù)共享復(fù)雜但是同步簡單,各個進程之間互不干擾;而線程共享所屬進程占有的內(nèi)存地址空間和資源,數(shù)據(jù)共享簡單,但是同步復(fù)雜。
  • 進程單獨占有一定的內(nèi)存地址空間,一個進程出現(xiàn)問題不會影響其他進程,不影響主程序的穩(wěn)定性,可靠性高;一個線程崩潰可能影響整個程序的穩(wěn)定性,可靠性較低。
  • 進程單獨占有一定的內(nèi)存地址空間,進程的創(chuàng)建和銷毀不僅需要保存寄存器和棧信息,還需要資源的分配回收以及頁調(diào)度,開銷較大;線程只需要保存寄存器和棧信息,開銷較小。

另外一個重要區(qū)別是,進程是操作系統(tǒng)進行資源分配的基本單位,而線程是操作系統(tǒng)進行調(diào)度的基本單位,即CPU分配時間的單位 。

上下文切換

上下文切換(有時也稱做進程切換或任務(wù)切換)是指 CPU 從一個進程(或線程)切換到另一個進程(或線程)。上下文是指某一時間點 CPU 寄存器和程序計數(shù)器的內(nèi)容。

  • 寄存器是cpu內(nèi)部的少量的速度很快的閃存,通常存儲和訪問計算過程的中間值提高計算機程序的運行速度。

  • 程序計數(shù)器是一個專用的寄存器,用于表明指令序列中 CPU 正在執(zhí)行的位置,存的值為正在執(zhí)行的指令的位置或者下一個將要被執(zhí)行的指令的位置,具體實現(xiàn)依賴于特定的系統(tǒng)。

CPU通過為每個線程分配CPU時間片來實現(xiàn)多線程機制。CPU通過時間片分配算法來循環(huán)執(zhí)行任務(wù),當前任務(wù)執(zhí)行一個時間片后會切換到下一個任務(wù)。

但是,在切換前會保存上一個任務(wù)的狀態(tài),以便下次切換回這個任務(wù)時,可以再加載這個任務(wù)的狀態(tài)。所以任務(wù)從保存到再加載的過程就是一次上下文切換。

上下文切換通常是計算密集型的,意味著此操作會消耗大量的 CPU 時間,故線程也不是越多越好。如何減少系統(tǒng)中上下文切換次數(shù),是提升多線程性能的一個重點課題。

線程的創(chuàng)建

1、實現(xiàn)Runnable接口

public class MyRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("我是實現(xiàn)Runnable接口。。");
    }

    public static void main(String[] args) {
        MyRunnable myRunner = new MyRunnable();
        Thread thread = new Thread(myRunner);
        thread.start();
    }
}

2、繼承Thread類

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("我是繼承Thread類。。");
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

3、實現(xiàn)Callable接口

public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        return 123;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }
}

4、通過線程池創(chuàng)建線程

看過《阿里Java開發(fā)手冊》的你,應(yīng)該知道

線程池不允許使用Executors去創(chuàng)建,而是通過ThreadPoolExecutor的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運行規(guī)則,規(guī)避資源耗盡的風險。

4. 【強制】線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式,這
樣的處理方式讓寫的同學(xué)更加明確線程池的運行規(guī)則,規(guī)避資源耗盡的風險。
說明:Executors 返回的線程池對象的弊端如下:
1FixedThreadPoolSingleThreadPool:
允許的請求隊列長度為 Integer.MAX_VALUE,可能會堆積大量的請求,從而導(dǎo)致 OOM。 
2CachedThreadPoolScheduledThreadPool:
允許的創(chuàng)建線程數(shù)量為 Integer.MAX_VALUE,可能會創(chuàng)建大量的線程,從而導(dǎo)致 OOM。

ThreadPoolExecutor機制

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

下面是ThreadPoolExecutor最核心的構(gòu)造方法參數(shù):

  1. corePoolSize 核心線程池的大??;
  2. maximumPoolSize 最大線程池大小;
  3. keepAliveTime 線程池中超過corePoolSize數(shù)目的空閑線程最大存活時間;可以allowCoreThreadTimeOut(true)使得核心線程超出有效時間也關(guān)閉;
  4. TimeUnit keepAliveTime的時間單位;
  5. workQueue阻塞任務(wù)隊列;
  6. threadFactory新建線程工廠;
  7. RejectedExecutionHandler當提交任務(wù)數(shù)超過maximumPoolSize+workQueue之和時,任務(wù)會交給RejectedExecutionHandler來處理;

重點講解

corePoolSizemaximumPoolSize,workQueue三者之間的關(guān)系:

  1. 當線程池小于corePoolSize時,新提交的任務(wù)會創(chuàng)建一個新線程執(zhí)行任務(wù),即使線程池中仍有空閑線程。
  2. 當線程池達到corePoolSize時,新提交的任務(wù)將被放在workQueue中,等待線程池中的任務(wù)執(zhí)行完畢。
  3. workQueue滿了,并且maximumPoolSize > corePoolSize時,新提交任務(wù)會創(chuàng)建新的線程執(zhí)行任務(wù)。
  4. 當提交任務(wù)數(shù)超過maximumPoolSize,新任務(wù)就交給RejectedExecutionHandler來處理。
  5. 當線程池中超過 corePoolSize線程,空閑時間達到keepAliveTime時,關(guān)閉空閑線程。
  6. 當設(shè)置allowCoreThreadTimeOut(true)時,線程池中corePoolSize線程空閑時間達到keepAliveTime也將關(guān)閉。

線程的生命周期

  1. NEW:初始狀態(tài),線程被構(gòu)建,但是還沒有調(diào)用 start 方法。
  2. RUNNABLED:運行狀態(tài),JAVA 線程把操作系統(tǒng)中的就緒和運行兩種狀態(tài)統(tǒng)一稱為“運行中”。調(diào)用線程的 start() 方法使線程進入就緒狀態(tài)。
  3. BLOCKED:阻塞狀態(tài),表示線程進入等待狀態(tài),也就是線程因為某種原因放棄了 CPU 使用權(quán)。比如訪問 synchronized 關(guān)鍵字修飾的方法,沒有獲得對象鎖。
  4. Waiting :等待狀態(tài),比如調(diào)用wait()方法。
  5. TIME_WAITING:超時等待狀態(tài),超時以后自動返回。比如調(diào)用 sleep(long millis) 方法
  6. TERMINATED:終止狀態(tài),表示當前線程執(zhí)行完畢。

看下源碼:

public enum State {          
    NEW,     
    RUNNABLE,       
    BLOCKED,             
    WAITING,           
    TIMED_WAITING,       
    TERMINATED; 
} 

線程的優(yōu)先級

  1. 線程的最小優(yōu)先級:1
  2. 線程的最大優(yōu)先級:10
  3. 線程的默認優(yōu)先級:5
  4. 通過調(diào)用 getPriority()setPriority(int newPriority) 方法來獲得和設(shè)置線程的優(yōu)先級

看下源碼:

/**
 * The minimum priority that a thread can have.
 */
public final static int MIN_PRIORITY = 1;

/**
 * The default priority that is assigned to a thread.
 */
public final static int NORM_PRIORITY = 5;

/**
 * The maximum priority that a thread can have.
 */
public final static int MAX_PRIORITY = 10;

看下代碼:

public class MyThread extends Thread {

    public static void main(String[] args) {
        MyThread a = new MyThread();
        System.out.println(a.getPriority());//5
        a.setPriority(8);
        System.out.println(a.getPriority());//8
    }
}

特性:

  1. 繼承性:比如A線程啟動B線程,則B線程的優(yōu)先級與A是一樣的。

  2. 規(guī)則性:高優(yōu)先級的線程總是大部分先執(zhí)行完,但不代表高優(yōu)先級線程全部先執(zhí)行完。

  3. 隨機性:優(yōu)先級較高的線程不一定每一次都先執(zhí)行完。

線程的停止

  1. stop() 方法,這個方法已經(jīng)標記為過時了,強制停止線程,相當于kill -9。
  2. interrupt() 方法,優(yōu)雅的停止線程。告訴線程可以停止了,至于線程什么時候停止,取決于線程自身。

看下停止線程的代碼:

public class InterruptDemo {
    private static int i ;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            //默認情況下isInterrupted 返回 false、通過 thread.interrupt 變成了 true
            while (!Thread.currentThread().isInterrupted()) {
                i++;
            }
            System.out.println("Num:" + i);
        }, "interruptDemo");
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt(); //不加這句,thread線程不會停止
    }
}

看上面這段代碼,主線程main方法調(diào)用 thread線程的 interrupt() 方法,就是告訴 thread 線程,你可以停止了(其實是將 thread 線程的一個屬性設(shè)置為了true),然后 thread 線程通過 isInterrupted() 方法獲取這個屬性來判斷是否設(shè)置為了true。

小結(jié)

以上介紹了一些java線程的一些基本知識,掌握了進程與線程的概念以及線程的創(chuàng)建、生命周期、停止等概念,后面我們再來詳細聊聊java并發(fā)相關(guān)的知識。文章來源地址http://www.zghlxwxcb.cn/news/detail-471509.html

到了這里,關(guān)于java并發(fā)編程:多線程基礎(chǔ)知識介紹的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【JUC-1】java多線程線程基礎(chǔ)知識

    【JUC-1】java多線程線程基礎(chǔ)知識

    繼承Thread類. 實現(xiàn)Runable接口. 實現(xiàn)Callable接口. Runable/Callable接口的實現(xiàn), 都是重寫其中的run/call方法, 實現(xiàn)任務(wù)邏輯, 再由線程執(zhí)行器(可以是Thread類,也可以是線程池)并發(fā)執(zhí)行run/call的邏輯. 而Thread類中的包含start方法, 可以控制線程啟動,執(zhí)行任務(wù). 當發(fā)生線程上下文切換時, 操作系

    2024年02月11日
    瀏覽(25)
  • java基礎(chǔ)之線程知識點

    java基礎(chǔ)之線程知識點

    操作系統(tǒng)(OS)中并發(fā)(同時)執(zhí)行的多個程序任務(wù) 宏觀并行,微觀串行 在一個時間段內(nèi),CPU會將時間段劃分為若干個時間片,一個時間片是能被一個程序擁有,且只有擁有時間片的程序才能執(zhí)行自身內(nèi)容,所以當時間片的劃分足夠細小,交替頻率足夠快,就會形成并行的假象,時間上仍然是

    2024年02月01日
    瀏覽(91)
  • Java面試_并發(fā)編程_線程基礎(chǔ)

    Java面試_并發(fā)編程_線程基礎(chǔ)

    進程是正在運行程序的實例, 進程中包含了線程, 每個線程執(zhí)行不同的任務(wù) 不同的進程使用不同的內(nèi)存空間, 在當前進程下的所有線程可以共享內(nèi)存空間 線程更輕量, 線程上下文切換成本一般上要比進程上下文切換低(上下文切換指的是從一個線程切換到另一個線程) 并發(fā)是單個

    2024年02月07日
    瀏覽(30)
  • 【Java】遨游在多線程的知識體系中(基礎(chǔ)篇一)

    【Java】遨游在多線程的知識體系中(基礎(chǔ)篇一)

    因為知識比較多,想把文章字數(shù)控制在一定范圍之內(nèi),本文只有先發(fā)一篇多線程部分篇幅,之后的知識也會馬上趕出來的,有什么有問題的地方經(jīng)管提出,會虛心接受,并且認真改正。 創(chuàng)建一個子類繼承自Thread,重寫Thread中的run方法, 這個方法內(nèi)部就包含了這個線程要執(zhí)行

    2024年02月01日
    瀏覽(16)
  • Java基礎(chǔ)知識篇——Java基本介紹

    Java基礎(chǔ)知識篇——Java基本介紹

    Java 是 Sun Microsystems 于 1995 年首次發(fā)布的一種 編程語言 和計算平臺。編程語言還是比較好理解的,什么是 計算平臺 呢? 計算平臺是電腦中運行應(yīng)用程序(軟件的環(huán)境),包括硬件環(huán)境和軟件環(huán)境。一般系統(tǒng)平臺包括一臺電腦的硬件體系結(jié)構(gòu),操作系統(tǒng)、運行時庫。 Java 是快

    2024年03月11日
    瀏覽(95)
  • 《Java SE》網(wǎng)絡(luò)編程基礎(chǔ)知識歸納。

    《Java SE》網(wǎng)絡(luò)編程基礎(chǔ)知識歸納。

    目錄 一、網(wǎng)絡(luò)基本介紹 1、什么是網(wǎng)絡(luò)通信? 2、網(wǎng)絡(luò) 3、IP地址 4、域名 5、網(wǎng)絡(luò)通信協(xié)議 6、Socket 二、TCP網(wǎng)絡(luò)通信編程 ?1、應(yīng)用實例1(字節(jié)流) 2、應(yīng)用實例2(字節(jié)流) 3、應(yīng)用實例3(字符流) 4、netstat 指令 三、UDP網(wǎng)絡(luò)通信編程? 1、基本介紹 2、基本流程 3、應(yīng)用實例 ?

    2024年01月20日
    瀏覽(31)
  • JAVA基礎(chǔ)知識-進制的介紹與書寫格式

    JAVA基礎(chǔ)知識-進制的介紹與書寫格式

    代碼 : 1.3.1 : 十進制到二進制的轉(zhuǎn)換 公式 :除基取余使用源數(shù)據(jù),不斷的除以基數(shù)(幾進制,基數(shù)就是幾)得到余數(shù),直到商為0,再將余數(shù)倒著拼起來即可。 需求 :將十進制數(shù)字11,轉(zhuǎn)換為2進制。 實現(xiàn)方式 :源數(shù)據(jù)為11,使用11不斷的除以基數(shù),也就是2,直到商為0。 1.

    2024年02月14日
    瀏覽(17)
  • [Java基礎(chǔ)系列第5彈]Java多線程:一篇讓你輕松掌握并發(fā)編程的指南

    多線程是一種編程技術(shù),它可以讓一個程序同時執(zhí)行多個任務(wù),從而提高程序的性能和效率。但是,使用Java多線程也不是一件容易的事情,它涉及到很多復(fù)雜的概念和問題,如線程安全、同步、鎖、原子類、并發(fā)集合、生產(chǎn)者消費者模式、線程池模式、Future模式、線程協(xié)作模

    2024年02月14日
    瀏覽(26)
  • Java入門高頻考查算法邏輯基礎(chǔ)知識3-編程篇(超詳細18題1.8萬字參考編程實現(xiàn))

    準備這些面試題時,請考慮如下準備步驟: 理解問題并澄清任何可能的疑點。確保你了解了面試官的期望,包括問題限制條件和期望的解決方案。 如果可能且適用的話,嘗試先給出一個簡單的解決方案,比如暴力法,然后再逐步優(yōu)化它。 在優(yōu)化之前,先分析暴力解法的效率

    2024年01月18日
    瀏覽(27)
  • Java 學(xué)習路線:基礎(chǔ)知識、數(shù)據(jù)類型、條件語句、函數(shù)、循環(huán)、異常處理、數(shù)據(jù)結(jié)構(gòu)、面向?qū)ο缶幊?、包、文件?API

    Java 是一種由 Sun Microsystems 于 1995 年首次發(fā)布的編程語言和計算平臺。Java 是一種通用的、基于類的、面向?qū)ο蟮木幊陶Z言,旨在減少實現(xiàn)依賴性。它是一個應(yīng)用程序開發(fā)的計算平臺。Java 快速、安全、可靠,因此在筆記本電腦、數(shù)據(jù)中心、游戲機、科學(xué)超級計算機、手機等領(lǐng)

    2024年03月24日
    瀏覽(39)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包