日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

老后端被借調去寫Java了,含淚總結的Java多線程編程基礎

來源: 責編: 時間:2023-12-21 17:10:49 199觀看
導讀這篇文章咱們總結一下 Java線程的基礎,打好基礎,后面幾篇再學多線程的同步控制中的各種鎖、線程通信等方面的知識時就會覺得更容易些。本文的大綱如下:線程在計算機系統里每個進程(Process)都代表著一個運行著的程序,比如打

這篇文章咱們總結一下 Java線程的基礎,打好基礎,后面幾篇再學多線程的同步控制中的各種鎖、線程通信等方面的知識時就會覺得更容易些。5aj28資訊網——每日最新資訊28at.com

本文的大綱如下:5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

線程

在計算機系統里每個進程(Process)都代表著一個運行著的程序,比如打開微信,系統就會為微信開一個進程--進程是對運行時程序的封裝,是系統進行資源調度和分配的基本單位。5aj28資訊網——每日最新資訊28at.com

一個進程下可以有很多個線程,還拿微信舉例子,我們用微信的時候除了給好友收發消息,還可以在里面看公眾號,看公眾號的時候,也不影響我們的微信收到其他人發給我們的消息,這就以為著運行的微信的進程,還開啟了多個線程來同時完成這些子任務。5aj28資訊網——每日最新資訊28at.com

線程是進程的子任務,是CPU調度和分派的基本單位,用于保證程序的實時性,實現進程內部的并發,線程同時也是操作系統可識別的最小執行和調度單位。5aj28資訊網——每日最新資訊28at.com

在 Java 里線程是程序執行的載體,我們寫的代碼就是由線程運行的。有的時候為了增加程序的執行效率,我們不得不使用多線程進行編程,雖然多線程能最大化程序利用 CPU 的效率,但是程序用多寫成進行任務處理,也是BUG的高發地,主要原因還是多線程環境下有些問題一旦被疏忽就會造成執行結果不符合預期的BUG。5aj28資訊網——每日最新資訊28at.com

平時我們寫代碼思考問題時的習慣思維是單線程的,寫多線程的時候得刻意切換一下才行,這就要求我們要了解清楚線程在不同運行條件下所表現出來的行為才行。5aj28資訊網——每日最新資訊28at.com

首先我們來看一下在 Java 中是怎么表示線程的。5aj28資訊網——每日最新資訊28at.com

Java 中的線程

到目前為止,我們寫的所有 Java 程序代碼都是在由JVM給創建的主線程(Main Thread) 中執行的。Java 線程就像一個虛擬 CPU,可以在運行的 Java 應用程序中執行 Java 代碼。當一個 Java 應用程序啟動時,它的入口方法 main() 方法由主線程執行。主線程(Main Thread)是一個由 Java 虛擬機創建的運行應用程序的特殊線程。5aj28資訊網——每日最新資訊28at.com

我們在 Java 里萬物皆對象,所以系統的線程在 Java 里也是用對象表示的,線程是類 java.lang.Thread 類或者其子類的實例。在 Java 應用程序內部, 我們可以通過線程對象創建和啟動更多線程,這些線程可以與主線程并行執行應用程序的代碼。5aj28資訊網——每日最新資訊28at.com

下面看一下怎么在 Java 程序里創建和啟動線程。5aj28資訊網——每日最新資訊28at.com

創建和啟動線程

在 Java 中創建一個線程,就是創建一個Thread類的實例5aj28資訊網——每日最新資訊28at.com

 Thread thread = new Thread();

啟動線程就是調用Thread對象的start()方法5aj28資訊網——每日最新資訊28at.com

  thread.start();

當然,這個例子沒有指定線程要執行的代碼,所以線程將在啟動后立即停止。 讓線程執行邏輯,需要給線程對象指定執行體。5aj28資訊網——每日最新資訊28at.com

指定線程要執行的代碼

有兩種方法可以給線程指定要執行的代碼。5aj28資訊網——每日最新資訊28at.com

  • 第一種是,創建Thread類的子類,在子類中覆蓋Thread類的run() 方法,在這個run() 方法的方法體里的代碼,就是指定給線程去執行的代碼。
  • 第二種是,將實現 Runnable (java.lang.Runnable) 的對象傳遞給Thread構造方法,創建Thread實例。

其實,還有第三種給線程指定執行代碼的方法,不過細究下來算是第二種方法的特殊使用方式,下面我們看看這三種指定線程執行方法體的方式,以及它們之間的區別。5aj28資訊網——每日最新資訊28at.com

1.通過 Thread 子類指定要執行的代碼

通過繼承Thread類創建線程的步驟:5aj28資訊網——每日最新資訊28at.com

(1) 定義 Thread 類的子類,并覆蓋該類的 run() 方法。run() 方法的方法體就代表了線程要完成的任務,因此把 run() 方法稱為執行體。5aj28資訊網——每日最新資訊28at.com

(2) 創建 Thread 子類的實例,即創建了線程對象。5aj28資訊網——每日最新資訊28at.com

(3) 調用線程對象的 start() 方法來啟動該線程。5aj28資訊網——每日最新資訊28at.com

package com.learnthread;public class ThreadFirstRunDemo {    public static void main(String[] args) {        // 實例化線程對象        MyThread threadA = new MyFirstThread("線程-A");        MyThread threadB = new MyFirstThread("線程-B");        // 啟動線程        threadA.start();        threadB.start();    }    static class MyFirstThread extends Thread {        private int ticket = 5;        MyThread(String name) {            super(name);        }        @Override        public void run() {            while (ticket > 0) {                System.out.println(Thread.currentThread().getName() + " 賣出了第 " + ticket + " 張票");                ticket--;            }        }    }}

上面的程序,主線程啟動調用A、B兩個線程的start() 后,并沒有通過調用wait() 等待他們執行結束。A、B兩個線程的執行體,會并發地被系統執行,等線程都直接結束后,程序才會退出。5aj28資訊網——每日最新資訊28at.com

2.通過實現 Runnable 接口指定要執行的代碼

Runnable 接口的定義如下,只有一個 run() 方法的定義:5aj28資訊網——每日最新資訊28at.com

package java.lang;public interface Runnable {    public abstract void run();}

其實,Thread 類實現的也是 Runnable 接口。 在 Thread 類的重載構造方法里,支持接收一個實現了 Runnale 接口的對象作為其 target 參數來初始化線程對象。5aj28資訊網——每日最新資訊28at.com

public class Thread implements Runnable {        ... public Thread(Runnable target) {        init(null, target, "Thread-" + nextThreadNum(), 0);    }        ...    public Thread(Runnable target, String name) {        init(null, target, name, 0);    }    ...}

通過實現 Runnable 接口創建線程的步驟如下:5aj28資訊網——每日最新資訊28at.com

(1) 定義 Runnable 接口的實現,實現該接口的 run 方法。該 run 方法的方法體同樣是線程的執行體。5aj28資訊網——每日最新資訊28at.com

(2) 創建 Runnable 實現類的實例,并以此實例作為 Thread 的 target 參數來創建 Thread 對象,該 Thread 對象才是真正的線程對象。5aj28資訊網——每日最新資訊28at.com

(3) 調用線程對象的 start 方法來啟動線程并執行。5aj28資訊網——每日最新資訊28at.com

package com.learnthread;public class RunnableThreadDemo {    public static void main(String[] args) {        // 實例化線程對象        Thread threadA = new Thread(new MyThread(), "Runnable 線程-A");        Thread threadB = new Thread(new MyThread(), "Runnable 線程-B");        // 啟動線程        threadA.start();        threadB.start();    }    static class MyThread implements Runnable {        private int ticket = 5;        @Override        public void run() {            while (ticket > 0) {                System.out.println(Thread.currentThread().getName() + " 賣出了第 " + ticket + " 張票");                ticket--;            }        }    }}

運行上面例程會有以下輸出,同樣程序會在所以線程執行完后退出。5aj28資訊網——每日最新資訊28at.com

Runnable 線程-B 賣出了第 5 張票Runnable 線程-B 賣出了第 4 張票Runnable 線程-B 賣出了第 3 張票Runnable 線程-B 賣出了第 2 張票Runnable 線程-B 賣出了第 1 張票Runnable 線程-A 賣出了第 5 張票Runnable 線程-A 賣出了第 4 張票Runnable 線程-A 賣出了第 3 張票Runnable 線程-A 賣出了第 2 張票Runnable 線程-A 賣出了第 1 張票Process finished with exit code 0

既然是給 Thread 傳遞 Runnable 接口的實現對象即可,那么除了普通的定義類實現接口的方式,我們還可以使用匿名類和 Lambda 表達式的方式來定義 Runnable 的實現。5aj28資訊網——每日最新資訊28at.com

  • 使用 Runnable 的匿名類作為參數創建 Thread 對象:
Thread threadA = new Thread(new Runnable() {    private int ticket = 5;    @Override    public void run() {        while (ticket > 0) {            System.out.println(Thread.currentThread().getName() + " 賣出了第 " + ticket + " 張票");            ticket--;        }    }}, "Runnable 線程-A");
  • 使用實現了 Runnable 的 Lambda 表達式作為參數創建 Thread 對象:
Runnable runnable = () -> { System.out.println("Lambda Runnable running"); };Thread threadB = new Thread(runnable, "Runnable 線程-B");

因為,Lambda 是無狀態的,定義不了內部屬性,這里就舉個簡單的打印一行輸出的例子了,理解一下這種用法即可。5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

3.獲取線程的執行結果

上面兩種方法雖然能指定線程執行體里要執行的任務,但是都沒有返回值,如果想讓線程的執行體方法有返回值,且能被外部創建它的父線程獲取到返回值,就需要結合J.U.C 里提供的 Callable、Future 接口來實現線程的執行體方法才行。5aj28資訊網——每日最新資訊28at.com

J.U.C 是 java.util.concurrent 包的縮寫,提供了很多并發編程的工具類,后面會詳細學習。5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

Callable 接口只聲明了一個方法,這個方法叫做 call():5aj28資訊網——每日最新資訊28at.com

package java.util.concurrent;public interface Callable<V> {    V call() throws Exception;}

Future 就是對于具體的 Callable 任務的執行進行取消、查詢是否完成、獲取執行結果的。可以通過 get 方法獲取 Callable 的 call 方法的執行結果,但是要注意該方法會阻塞直到任務返回結果。5aj28資訊網——每日最新資訊28at.com

public interface Future<V> {    boolean cancel(boolean mayInterruptIfRunning);    boolean isCancelled();    boolean isDone();    V get() throws InterruptedException, ExecutionException;    V get(long timeout, TimeUnit unit)        throws InterruptedException, ExecutionException, TimeoutException;}

Java 的 J.U.C 里給出了 Future 接口的一個實現 FutureTask,它同時實現了 Future 和 Runnable 接口,所以,FutureTask 既可以作為 Runnable 被線程執行,又可以作為 Future 得到 Callable 的返回值。5aj28資訊網——每日最新資訊28at.com

下面是一個 Callable 實現類和 FutureTask 結合使用讓主線程獲取子線程執行結果的一個簡單的示例:5aj28資訊網——每日最新資訊28at.com

package com.learnthread;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;public class CallableDemo implements Callable<Integer> {    @Override    public Integer call() {        int i = 0;        for (i = 0; i < 20; i++) {            if (i == 5) {                break;            }            System.out.println(Thread.currentThread().getName() + " " + i);        }        return i;    }    public static void main(String[] args) {        CallableDemo tt = new CallableDemo();        FutureTask<Integer> ft = new FutureTask<>(tt);        Thread t = new Thread(ft);        t.start();        try {            System.out.println(Thread.currentThread().getName() + " " + ft.get());        } catch (Exception e) {            e.printStackTrace();        }    }}

上面我們把 FutureTask 作為 Thread 構造方法的 Runnable 類型參數 target 的實參,在它的基礎上創建線程, 執行邏輯。所以本質上 Callable + FutureTask 這種方式也是第二種通過實現 Runnable 接口給線程指定執行體的,只不過是由 FutureTask 包裝了一層,由它的 run 方法再去調用 Callable 的 call 方法。例程運行后的輸出如下:5aj28資訊網——每日最新資訊28at.com

Thread-0 0Thread-0 1Thread-0 2Thread-0 3Thread-0 4main 5

Callable 更常用的方式是結合線程池來使用,在線程池接口 ExecutorService 中定義了多個可接收 Callable 作為線程執行任務的方法 submit、invokeAny、invokeAll 等,這個等學到線程池了我們再去學習。5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

Java 線程的使用陷阱

在剛開始接觸和學習 Java 線程相關的知識時,一個常見的錯誤是,在創建線程的線程里,調用 Thread 對象的 run() 方法而不是調用 start() 方法。5aj28資訊網——每日最新資訊28at.com

Runnable myRunnable = new Runnable() {    @Override    public void run() {  System.out.println("Anonymous Runnable running");    }};Thread newThread = new Thread(myRunnable);newThread.run();  // 應該調用 newThread.start();

起初你可能沒有注意到這么干有啥錯,因為 Runnable 的 run() 方法正常地被執行,輸出了我們想要的結果。5aj28資訊網——每日最新資訊28at.com

但是,這么做 run() 不會由我們剛剛創建的新線程執行,而是由創建 newThread 對象的線程執行的 。要讓新創建的線程--newThread 調用 myRunnable 實例的 run() 方法,必須調用 newThread.start() 方法才行。5aj28資訊網——每日最新資訊28at.com

線程對象的基本用法

11.線程對象常用的方法

Thread 線程常用的方法有以下這些:5aj28資訊網——每日最新資訊28at.com

方法
5aj28資訊網——每日最新資訊28at.com

描述
5aj28資訊網——每日最新資訊28at.com

run5aj28資訊網——每日最新資訊28at.com

線程的執行實體,不需要我們主動調用,調用線程的start() 就會執行run() 方法里的執行體
5aj28資訊網——每日最新資訊28at.com

start
5aj28資訊網——每日最新資訊28at.com

線程的啟動方法。
5aj28資訊網——每日最新資訊28at.com

Thread.currentThread
5aj28資訊網——每日最新資訊28at.com

Thread 類提供的靜態方法,返回對當前正在執行的線程對象的引用。
5aj28資訊網——每日最新資訊28at.com

setName
5aj28資訊網——每日最新資訊28at.com

設置線程名稱。
5aj28資訊網——每日最新資訊28at.com

getName
5aj28資訊網——每日最新資訊28at.com

獲取線程名稱。
5aj28資訊網——每日最新資訊28at.com

setPriority
5aj28資訊網——每日最新資訊28at.com

設置線程優先級。Java 中的線程優先級的范圍是 [1,10],一般來說,高優先級的線程在運行時會具有優先權。可以通過 thread.setPriority(Thread.MAX_PRIORITY) 的方式設置,默認優先級為 5。
5aj28資訊網——每日最新資訊28at.com

getPriority
5aj28資訊網——每日最新資訊28at.com

獲取線程優先級。
5aj28資訊網——每日最新資訊28at.com

setDaemon
5aj28資訊網——每日最新資訊28at.com

設置線程為守護線程。
5aj28資訊網——每日最新資訊28at.com

isDaemon
5aj28資訊網——每日最新資訊28at.com

判斷線程是否為守護線程。
5aj28資訊網——每日最新資訊28at.com

isAlive
5aj28資訊網——每日最新資訊28at.com

判斷線程是否啟動。
5aj28資訊網——每日最新資訊28at.com

interrupt
5aj28資訊網——每日最新資訊28at.com

中斷線程的運行。
5aj28資訊網——每日最新資訊28at.com

Thread.interrupted
5aj28資訊網——每日最新資訊28at.com

測試當前線程是否已被中斷。
5aj28資訊網——每日最新資訊28at.com

join
5aj28資訊網——每日最新資訊28at.com

可以使一個線程強制運行,線程強制運行期間,其他線程無法運行,必須等待此線程完成之后才可以繼續執行。
5aj28資訊網——每日最新資訊28at.com

Thread.sleep
5aj28資訊網——每日最新資訊28at.com

靜態方法。將當前正在執行的線程休眠。
5aj28資訊網——每日最新資訊28at.com

Thread.yield
5aj28資訊網——每日最新資訊28at.com

靜態方法。將當前正在執行的線程暫停,讓出CPU,讓其他線程執行。
5aj28資訊網——每日最新資訊28at.com

2.線程休眠

使用 Thread.sleep 方法可以使得當前正在執行的線程進入休眠狀態。 使用 Thread.sleep 需要向其傳入一個整數值,這個值表示線程將要休眠的毫秒數。 Thread.sleep 方法可能會拋出 InterruptedException,因為異常不能跨線程傳播回主線程中,因此必須在本地進行處理。線程中拋出的其它異常也同樣需要在本地進行處理。5aj28資訊網——每日最新資訊28at.com

public class ThreadSleepDemo {    public static void main(String[] args) {        new Thread(new MyThread("線程A", 500)).start();        new Thread(new MyThread("線程B", 1000)).start();        new Thread(new MyThread("線程C", 1500)).start();    }    static class MyThread implements Runnable {        /** 線程名稱 */        private String name;        /** 休眠時間 */        private int time;        private MyThread(String name, int time) {            this.name = name;            this.time = time;        }        @Override        public void run() {            try {                // 休眠指定的時間                Thread.sleep(this.time);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(this.name + "休眠" + this.time + "毫秒。");        }    }}

上面例程開啟了3個線程,在各自的線程執行體里讓各自線程休眠了 500、1000 和 1500 ms ,線程 C 休眠結束后,整個程序退出。5aj28資訊網——每日最新資訊28at.com

線程A休眠500毫秒。線程B休眠1000毫秒。線程C休眠1500毫秒。Process finished with exit code 0

3.終止線程

當一個線程運行時,另一個線程可以直接通過 interrupt 方法中斷其運行狀態。5aj28資訊網——每日最新資訊28at.com

public class ThreadInterruptDemo {    public static void main(String[] args) {        MyThread mt = new MyThread(); // 實例化Runnable實現類的對象        Thread t = new Thread(mt, "線程"); // 實例化Thread對象        t.start(); // 啟動線程        try {            Thread.sleep(2000); // 主線程休眠2秒        } catch (InterruptedException e) {            System.out.println("主線程休眠被終止");        }        t.interrupt(); // 中斷 mt 線程的執行    }    static class MyThread implements Runnable {        @Override        public void run() {            System.out.println("1、進入run()方法");            try {                Thread.sleep(10000); // 線程休眠10秒                System.out.println("2、已經完成了休眠");            } catch (InterruptedException e) {                System.out.println("3、MyThread線程休眠被終止");                return; // 返回調用處            }            System.out.println("4、run()方法正常結束");        }    }}

如果一個線程的 run 方法執行一個無限循環,并且沒有執行 sleep 等會拋出 InterruptedException 的操作,那么調用線程的 interrupt 方法就無法使線程提前結束。5aj28資訊網——每日最新資訊28at.com

不過調用 interrupt 方法會設置線程的中斷標記,此時被設置中斷標記的線程再調用 interrupted 方法會返回 true。因此可以在線程的執行體循環體中使用 interrupted 方法來判斷當前線程是否處于中斷狀態,從而提前結束線程。5aj28資訊網——每日最新資訊28at.com

看下面這個,可以有效終止線程執行的示例:5aj28資訊網——每日最新資訊28at.com

package com.learnthread;import java.util.concurrent.TimeUnit;public class ThreadInterruptEffectivelyDemo {    public static void main(String[] args) throws Exception {        MyTask task = new MyTask();        Thread thread = new Thread(task, "線程-A");        thread.start();        TimeUnit.MILLISECONDS.sleep(50);        thread.interrupt();    }    private static class MyTask implements Runnable {        private volatile long count = 0L;        @Override        public void run() {            System.out.println(Thread.currentThread().getName() + " 線程啟動");            // 通過 Thread.interrupted 和 interrupt 配合來控制線程終止            while (!Thread.interrupted()) {                System.out.println(count++);            }            System.out.println(Thread.currentThread().getName() + " 線程終止");        }    }}

主線程在啟動線程-A后,主動休眠50毫秒,線程-A的執行體里會不斷打印計數器的值,等休眠結束后主線程通過調用線程-A的 interrupt 方法設置了線程的中斷標記,這時線程-A的執行體中通過 Thread.interrupted() 就能判斷出線程被設置了中斷狀態,隨后結束執行退出。5aj28資訊網——每日最新資訊28at.com

4.守護線程

(1) 什么是守護線程?5aj28資訊網——每日最新資訊28at.com

  • 守護線程(Daemon Thread)是在后臺執行并且不會阻止 JVM 終止的線程。當所有非守護線程結束時,程序也就終止,同時會殺死所有守護線程。
  • 與守護線程(Daemon Thread)相反的,叫用戶線程(User Thread),也就是非守護線程。

(2) 為什么需要守護線程?5aj28資訊網——每日最新資訊28at.com

守護線程的優先級比較低,用于為系統中的其它對象和線程提供服務。典型的應用就是垃圾回收器。5aj28資訊網——每日最新資訊28at.com

(3) 如何使用守護線程?5aj28資訊網——每日最新資訊28at.com

可以使用 isDaemon 方法判斷線程是否為守護線程。5aj28資訊網——每日最新資訊28at.com

可以使用 setDaemon 方法設置線程為守護線程。5aj28資訊網——每日最新資訊28at.com

  • 正在運行的用戶線程無法設置為守護線程,所以 setDaemon 必須在 thread.start 方法之前設置,否則會拋出 llegalThreadStateException 異常;
  • 一個守護線程創建的子線程依然是守護線程。
  • 不要認為所有的應用都可以分配給守護線程來進行服務,比如讀寫操作或者計算邏輯就不能。
public class ThreadDaemonDemo {    public static void main(String[] args) {        Thread t = new Thread(new MyThread(), "線程");        t.setDaemon(true); // 此線程在后臺運行        System.out.println("線程 t 是否是守護進程:" + t.isDaemon());        t.start(); // 啟動線程    }    static class MyThread implements Runnable {        @Override        public void run() {            while (true) {                System.out.println(Thread.currentThread().getName() + "在運行。");            }        }    }}

Java 線程的生命周期

java.lang.Thread.State 中定義了 6 種不同的線程狀態,在給定的一個時刻,線程只能處于其中的一個狀態。 下圖給出了這六種狀態,注意中間的 Ready 和 Running 都屬于 Runnable 就緒狀態。5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

以下是各狀態的說明,以及狀態間的聯系:5aj28資訊網——每日最新資訊28at.com

  • 新建(New) - 尚未調用 start 方法的線程處于此狀態。此狀態意味著:線程創建了但尚未啟動。
  • 就緒(Runnable) - 已經調用了 start 方法的線程處于此狀態。此狀態意味著:線程已經在 JVM 中運行。但是在操作系統層面,它可能處于運行狀態,也可能等待資源調度(例如處理器資源),資源調度完成就進入運行狀態。所以該狀態的可運行是指可以被運行,具體有沒有運行要看底層操作系統的資源調度。
  • 阻塞(Blocked) - 此狀態意味著:線程處于被阻塞狀態。表示線程在等待 synchronized 的隱式鎖(Monitor lock)。被 synchronized 修飾的方法、代碼塊同一時刻只允許一個線程執行,其他線程只能等待,即處于阻塞狀態。當占用 synchronized 隱式鎖的線程釋放鎖,并且等待的線程獲得 synchronized 隱式鎖后,就又會從 BLOCKED 轉換到 RUNNABLE 狀態。
  • 等待(Waiting) - 此狀態意味著:線程無限期等待,直到被其他線程顯式地喚醒。 阻塞和等待的區別在于,阻塞是被動的,它是在等待獲取 synchronized 的隱式鎖。而等待是主動的,線程通過調用 Object.wait 等方法進入。
  • 定時等待(Timed waiting) - 此狀態意味著:無需等待其它線程顯式地喚醒,在一定時間之后會被系統自動喚醒,線程通過調用設置了 Timeout 參數的Object.wait 等方法進入。
  • 終止(Terminated) - 線程執行完 run 方法,或者因異常退出了 run 方法。此狀態意味著:線程結束了生命周期。

下面這張圖更生動地展示了線程狀態切換的時機和觸發條件(圖片來自網絡,出處下方飲用鏈接1)。5aj28資訊網——每日最新資訊28at.com

5aj28資訊網——每日最新資訊28at.com

引用鏈接:5aj28資訊網——每日最新資訊28at.com

  • https://dunwu.github.io/javacore/concurrent/Java%E7%BA%BF%E7%A8%8B%E5%9F%BA%E7%A1%80.html
  • https://www.cnblogs.com/pcheng/p/6905340.html

本文鏈接:http://www.www897cc.com/showinfo-26-51228-0.html老后端被借調去寫Java了,含淚總結的Java多線程編程基礎

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: PHP老矣,尚能飯否?

下一篇: 如何快速分析軟件運行瓶頸在哪里?推薦Linux下的一個強大命令工具

標簽:
  • 熱門焦點
  • 6月安卓手機好評榜:魅族20 Pro蟬聯冠軍

    性能榜和性價比榜之后,我們來看最后的安卓手機好評榜,數據來源安兔兔評測,收集時間2023年6月1日至6月30日,僅限國內市場。第一名:魅族20 Pro好評率:95%5月份的時候魅族20 Pro就是
  • 從 Pulsar Client 的原理到它的監控面板

    背景前段時間業務團隊偶爾會碰到一些 Pulsar 使用的問題,比如消息阻塞不消費了、生產者消息發送緩慢等各種問題。雖然我們有個監控頁面可以根據 topic 維度查看他的發送狀態,
  • 如何正確使用:Has和:Nth-Last-Child

    我們可以用CSS檢查,以了解一組元素的數量是否小于或等于一個數字。例如,一個擁有三個或更多子項的grid。你可能會想,為什么需要這樣做呢?在某些情況下,一個組件或一個布局可能會
  • 如何通過Python線程池實現異步編程?

    線程池的概念和基本原理線程池是一種并發處理機制,它可以在程序啟動時創建一組線程,并將它們置于等待任務的狀態。當任務到達時,線程池中的某個線程會被喚醒并執行任務,執行完任
  • 從零到英雄:高并發與性能優化的神奇之旅

    作者 | 波哥審校 | 重樓作為公司的架構師或者程序員,你是否曾經為公司的系統在面對高并發和性能瓶頸時感到手足無措或者焦頭爛額呢?筆者在出道那會為此是吃盡了苦頭的,不過也得
  • 一文搞定Java NIO,以及各種奇葩流

    大家好,我是哪吒。很多朋友問我,如何才能學好IO流,對各種流的概念,云里霧里的,不求甚解。用到的時候,現百度,功能雖然實現了,但是為什么用這個?不知道。更別說效率問題了~下次再遇到,
  • 零售大模型“干中學”,攀爬數字化珠峰

    文/侯煜編輯/cc來源/華爾街科技眼對于絕大多數登山愛好者而言,攀爬珠穆朗瑪峰可謂終極目標。攀登珠峰的商業路線有兩條,一是尼泊爾境內的南坡路線,一是中國境內的北坡路線。相
  • Temu起訴SHEIN,跨境電商戰事升級

    來源 | 伯虎財經(bohuFN)作者 | 陳平安日前據外媒報道,拼多多旗下跨境電商平臺Temu正對競爭對手SHEIN提起新訴訟,訴狀稱Shein&ldquo;利用市場支配力量強迫服裝廠商與之簽訂獨家
  • 微博大門常打開,迎接海外畫師漂洋東渡

    作者:互聯網那些事&ldquo;起猛了,我能看得懂日語了&rdquo;。&ldquo;為什么日本人說話我能聽懂?&rdquo;&ldquo;中文不像中文,日語不像日語,但是我竟然看懂了&rdquo;&hellip;&hell
Top 主站蜘蛛池模板: 遵义市| 孟津县| 宜兴市| 安溪县| 临泉县| 平阴县| 江源县| 阿克苏市| 上饶市| 喀喇| 古丈县| 永新县| 亚东县| 诸暨市| 会宁县| 南充市| 大足县| 绥芬河市| 礼泉县| 台东市| 宿州市| 荆州市| 石渠县| 迭部县| 红桥区| 靖宇县| 津市市| 桂阳县| 雷山县| 柳江县| 鹤庆县| 渝北区| 修水县| 五大连池市| 遂溪县| 延津县| 开原市| 乌什县| 平乐县| 湘西| 东阿县|