在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Java線程學習基礎詳解

電子設計 ? 來源:電子設計 ? 作者:電子設計 ? 2020-12-10 22:02 ? 次閱讀

線程基礎

1. 線程的生命周期

1.1 新建狀態:

  • 使用 new 關鍵字和 Thread 類或其子類建立一個線程對象后,該線程對象就處于新建狀態。它保持這個狀態直到程序 start() 這個線程。

1.2 就緒狀態:

  • 當線程對象調用了start()方法之后,該線程就進入就緒狀態。就緒狀態的線程處于就緒隊列中,要等待JVM里線程調度器的調度。

1.3 運行狀態:

  • 如果就緒狀態的線程獲取 CPU 資源,就可以執行 run(),此時線程便處于運行狀態。處于運行狀態的線程最為復雜,它可以變為阻塞狀態、就緒狀態和死亡狀態。

1.4 阻塞狀態:

  • 如果一個線程執行了sleep(睡眠)、suspend(掛起)等方法,失去所占用資源之后,該線程就從運行狀態進入阻塞狀態。在睡眠時間已到或獲得設備資源后可以重新進入就緒狀態。可以分為三種:

    • 等待阻塞:運行狀態中的線程執行 wait() 方法,使線程進入到等待阻塞狀態。
    • 同步阻塞:線程在獲取 synchronized 同步鎖失敗(因為同步鎖被其他線程占用)。
    • 其他阻塞:通過調用線程的 sleep() 或 join() 發出了 I/O 請求時,線程就會進入到阻塞狀態。當sleep() 狀態超時,join() 等待線程終止或超時,或者 I/O 處理完畢,線程重新轉入就緒狀態。

1.5 死亡狀態:

  • 一個運行狀態的線程完成任務或者其他終止條件發生時,該線程就切換到終止狀態。

2. 線程的優先級和守護線程

2.1 線程的優先級

  • 每一個 Java 線程都有一個優先級,這樣有助于操作系統確定線程的調度順序。
  • Java 線程的優先級是一個整數,其取值范圍是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
  • 默認情況下,每一個線程都會分配一個優先級 NORM_PRIORITY(5)。

2.2 守護線程

  • Java中有兩種線程:用戶線程和守護線程??梢酝ㄟ^isDeamon()方法來區別它們:如果返回false,則說明該線程是“用戶線程”;否則就是“守護線程”。
  • 用戶線程一般用戶執行用戶級任務,而守護線程也就是“后臺線程”,一般用來執行后臺任務。
  • 需要注意的是:JVM在“用戶線程”都結束后會退出。

3. 創建線程

3.1 通過實現 Runnable 接口

  • 步驟:

    • 創建類實現 Runnable 接口
    • 實現 run() 方法,線程實際運行的方法
    • 實現 start() 方法,里面實例化線程對象(new Thread(this, threadName)),調用線程對象的 start() 方法
  • 代碼實現

    package com.ljw.thread;
    
    public class RunnableDemo {
    
        public static void main(String[] args) {
            // 測試
            RunnableDemo R = new RunnableDemo();
            RunnableThread R1 = R.new RunnableThread("thread1");
            R1.start();
            
            RunnableThread R2 = R.new RunnableThread("thread2");
            R2.start();
    
        }
        
        
        class RunnableThread implements Runnable{
            private String threadName;
            private Thread t;
            
            public RunnableThread(String name) {
                // TODO Auto-generated constructor stub
                threadName = name;
                System.out.println("創建線程 "+threadName);
            }
    
            
            @Override
            public void run() {
                System.out.println("正在運行線程:"+threadName);
                
                try {
                    for(int i=10;i>0;i--) {
                        System.out.println("線程:"+threadName+" 正在打印:"+i);    
                        Thread.sleep(50);
                    }
                }catch(Exception e) {
                    e.printStackTrace();
                }
                
                System.out.println("線程:"+threadName+" 正在退出......");
            }
            
            public void start() {
                System.out.println("開始線程 "+threadName);
                if(t == null) {
                    t = new Thread(this, threadName);
                    t.start();
                }
            }
            
        }
    }
    

3.2 通過繼承 Thread 類本身

  • 步驟:

    • 創建類繼承 Thread 類
    • 下面與用Runnable接口一樣

3.3 通過 Callable 和 Future 創建線程

  • 步驟:

    • 創建 Callable 接口的實現類,并實現 call() 方法,該 call() 方法將作為線程執行體,并且有返回值。
    • 創建 Callable 實現類的實例,使用 FutureTask 類來包裝 Callable 對象,該 FutureTask 對象封裝了該 Callable 對象的 call() 方法的返回值。
    • 使用 FutureTask 對象作為 Thread 對象的 target 創建并啟動新線程。
    • 調用 FutureTask 對象的 get() 方法來獲得子線程執行結束后的返回值。
  • Callable接口與Runnable接口的區別:

    • Callable中call方法可以有返回值,而Runnable中的run方法沒有返回值
  • 代碼實現

    package com.ljw.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    public class CallableThreadTest implements Callable {
        public static void main(String[] args)  
        {  
            CallableThreadTest ctt = new CallableThreadTest();  
            FutureTask ft = new FutureTask<>(ctt);  
            for(int i = 0;i < 10;i++)  
            {  
                System.out.println(Thread.currentThread().getName()+" 的循環變量i的值"+i);  
                if(i%2==0)  
                {  
                    new Thread(ft,"有返回值的線程").start();  
                }  
            }  
            try  
            {  
                System.out.println("子線程的返回值:"+ft.get());  
            } catch (InterruptedException e)  
            {  
                e.printStackTrace();  
            } catch (Exception e)  
            {  
                e.printStackTrace();  
            }  
      
        }
        @Override  
        public Integer call() throws Exception  
        {  
            int i = 0;  
            for(;i<10;i++)  
            {  
                System.out.println(Thread.currentThread().getName()+" "+i);  
            }  
            return i;  
        }  
    }

4. synchronized關鍵字

4.1 概述

  • synchronized關鍵字是為了解決共享資源競爭的問題,共享資源一般是以對象形式存在的內存片段,但也可以是文件、輸入/輸出端口,或者是打印機。
  • 要控制對共享資源的訪問,得先把它包裝進一個對象。然后把所有要訪問的這個資源的方法標記為synchronized。
  • 如果某個任務處于一個對標記為synchronized的方法的調用中,那么在這個線程從該方法返回之前,其他所有要調用類中任何標記為synchronized方法的線程都會被阻塞。

4.2 基本原則

  • 第一條:當一個線程訪問某對象的synchronized方法或者synchronized代碼塊時,其他線程對該對象的該synchronized方法或者synchronized代碼塊的訪問將被阻塞。
  • 第二條:當一個線程訪問某對象的synchronized方法或者synchronized代碼塊時,其他線程仍然可以訪問該對象的非同步代碼塊。
  • 第三條:當一個線程訪問某對象的synchronized方法或者synchronized代碼塊時,其他線程對該對象的其他的synchronized方法或者synchronized代碼塊的訪問將被阻塞。

4.3 實例

  • 兩個相似的例子

    • 實例1:實現接口Runnable
    package com.ljw.thread;
    
    public class RunnableTest {
    
        public static void main(String[] args) {
            
            class MyRunnable implements Runnable{
                
                @Override
                public void run() {
                    synchronized (this) {
                        for(int i=0;i<5;i++) {
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName() + " 正在進行打印 " +i);
                        }
                    }
                }
            }
            
            Runnable runnable = new MyRunnable();
            Thread t1 = new Thread(runnable,"t1");
            Thread t2 = new Thread(runnable,"t2");
            
            t1.start();
            t2.start();
        }
    }

    運行結果:

    t1 正在進行打印 0
    t1 正在進行打印 1
    t1 正在進行打印 2
    t1 正在進行打印 3
    t1 正在進行打印 4
    t2 正在進行打印 0
    t2 正在進行打印 1
    t2 正在進行打印 2
    t2 正在進行打印 3
    t2 正在進行打印 4

    結果說明:run()方法中存在synchronized(this)代碼塊,而且t1和t2都是基于MyRunnable這個Runnable對象創建的線程。這就意味著,我們可以將synchronized(this)中的this看做是MyRunnable這個Runnable對象;因此,線程t1和t2共享“MyRunable對象的同步鎖”。所以,當一個線程運行的時候,另外一個線程必須等待正在運行的線程釋放MyRunnable的同步鎖之后才能運行。

    • 實例2:繼承Thread類
    public class ThreadTest {
        public static void main(String[] args) {
    
            class MyThread extends Thread{
                public MyThread(String name){
                    super(name);
                }
                @Override
                public void run() {
                    synchronized(this){
                        for(int i=0;i<10;i++){
                            try {
                                Thread.sleep(100);
                                System.out.println(Thread.currentThread().getName()+" 正在進行打印 "+i);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
            Thread t1 = new MyThread("t1");
            Thread t2 = new MyThread("t2");
            t1.start();
            t2.start();
        }
    }

    運行結果:

    t2 正在進行打印 0
    t1 正在進行打印 0
    t2 正在進行打印 1
    t1 正在進行打印 1
    t1 正在進行打印 2
    t2 正在進行打印 2
    t2 正在進行打印 3
    t1 正在進行打印 3
    t1 正在進行打印 4
    t2 正在進行打印 4

    對比結果:發現實例1的兩個線程是一個結束后,另一個才運行,實例2的是交叉運行,在run()方法中都有synchronized(this),為什么結果不一樣?

    分析:synchronized(this)中的this是指當前對象,即synchronized(this)所在類對應的當前對象。它的作用是獲取獲取當前對象的同步鎖。對于實例2中的synchronized(this)中的this代表的是MyThread對象,t1和t2是兩個不同的MyThread對象,因此t1和t2在執行synchronized(this)時獲取的是不同對象的同步鎖。對于實例1來說,synchronized(this)中的this代表的時候MyRunnable對象,t1t2共同一個MyRunnable對象,因此,一個線程獲取了對象的同步鎖,會造成另一個線程的等待。

4.4 synchronized方法和synchronized代碼塊

4.4.1 概述

  • synchronized方法是用synchronized修飾方法,這是一種粗粒度鎖;這個同步方法(非static方法)無需顯式指定同步監視器,同步方法的同步監視器是this,也就是調用該方法的對象。
  • synchronized代碼塊是用synchronized修飾代碼塊,這是一種細粒度鎖。線程開始執行同步代碼塊之前,必須先獲得對同步監視器的鎖定,任何時候只能有一個線程可以獲得對同步監視器的鎖定,當同步代碼塊執行完成后,該線程會釋放對同步監視器的鎖定。雖然Java允許使用任何對象作為同步監視器,但同步監視器的目的就是為了阻止兩個線程對同一個共享資源進行并發訪問,因此通常推薦使用可能被并發訪問的共享資源充當同步監視器。

4.4.2 實例

public class SnchronizedTest {

    public static void main(String[] args) {

        class Demo {
            // synchronized方法
             public synchronized void synMethod() {
                    for(int i=0; i<1000000; i++)
                        ;
                }
                
                public void synBlock() {
                    // synchronized代碼塊
                    synchronized( this ) {
                        for(int i=0; i<1000000; i++)
                            ;
                    }
                }
        }
    }
}

4.5 實例鎖和全局鎖

4.5.1 概述

  • 實例鎖:鎖在某個實例對象上。如果該類是單例,那么該鎖也是具有全局鎖的概念。實例鎖對應的就是synchronized關鍵字。
  • 全局鎖:該鎖針對的是類,無論實例多少個對象,那么線程都共享該鎖。全局鎖對應的就是static synchronized(或者是鎖在該類的class或者classloader對象上)。

4.5.2 實例

pulbic class Something {
    public synchronized void isSyncA(){}
    public synchronized void isSyncB(){}
    public static synchronized void cSyncA(){}
    public static synchronized void cSyncB(){}
}

假設,類Something有兩個實例(對象)分別為x和y。分析下面4組表達式獲取鎖的情況。

  • x.isSyncA()與x.isSyncB()

    • 不能同時訪問,因為都是訪問對象x的同步鎖
  • x.isSyncA()與y.isSyncA()

    • 可以同時訪問,因為是訪問不同對象(x和y)的同步鎖
  • x.cSyncA()與y.cSyncB()

    • 不能同時訪問,因為兩個方法是靜態的,相當于用Something.cSyncA()和Something.cSyncB()訪問,是相同的對象
  • x.isSyncA()與Something.cSyncA()

    • 可以同時訪問,因為訪問不同對象

5. Volatile 關鍵字

5.1 Volatile原理

  • Java語言提供了一種稍微同步機制,即volatile變量,用來確保將變量的更新操作通知其他線程
  • 在訪問volatile變量是不會執行加鎖操作,因此也就不會重新執行線程阻塞,volatile變量是一種比synchronized關鍵字輕量級的同步機制
  • 當一個變量被volatile修飾后,不但具有可見性,而且還禁止指令重排。volatile的讀性能消耗與普通變量幾乎相同,但是寫操作就慢一些,因為它要保證本地代碼中插入許多內存屏障指令來保證處理器不發生亂序執行

6. 線程等待和喚醒

6.1 常用方法

  • 在Object.java中,定義了wait(),notify()和notifyAll()等接口
  • wait()方法的作用是讓當前線程進入阻塞狀態,同時會釋放當前對象所持有的鎖
  • notify()喚醒當前對象上的等待線程,notifyAll()則是喚醒所有的線程

6.2 實例

package com.ljw.thread;

public class WaitDemo {
    public static void main(String[] args) {

        class ThreadTest extends Thread{
            
            @Override
            public void run() {
                synchronized (this) {
                    System.out.println("開始運行線程 "+Thread.currentThread().getName());
                    System.out.println("喚醒線程notify()");
                    notify();
                }
            }
        }
        
        ThreadTest thread1 = new ThreadTest();
        thread1.start();
        
        synchronized (thread1) {
            try {
                System.out.println("主線程進入阻塞,釋放thread對象的同步鎖,wait()");
                thread1.wait(); // wait()是讓當前線程進入阻塞狀態,wait()是在主線程中執行,
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("主線程繼續進行");
    }
}

7. 線程讓步和休眠

7.1 線程讓步

7.1.1 概述

  • 在Java線程中,yield()方法的作用是讓步,它能讓當前線程由“運行狀態”進入到“就緒狀態”,可能讓其它同級別的線程獲得執行權,但不一定,可能它自己再次由“就緒狀態”進入到“運行狀態”

7.1.2 實例

package com.ljw.thread;

public class YieldTest {

    public static void main(String[] args) {

        class ThreadA extends Thread{
            public ThreadA(String name){
                super(name);
            }
            
            @Override
            public synchronized void run() {

                for(int i=0;i<5;i++){
                    System.out.println(" "+this.getName()+" "+i);
                    
                    if(i%2 == 0){
                        Thread.yield();
                    }
                }
            }
        }
        
        ThreadA t1 = new ThreadA("t1");
        ThreadA t2 = new ThreadA("t2");
        t1.start();
        t2.start();
    }
}

運行結果(不唯一):

 t1 0
 t2 0
 t1 1
 t1 2
 t2 1
 t1 3
 t2 2
 t1 4
 t2 3
 t2 4

結果說明:
線程t1在能被2整除的時候,并不一定切換到線程2。這表明,yield()方法雖然可以讓線程由“運行狀態”進入到“就緒狀態”;但是,它不一定會讓其他線程獲取CPU執行權(其他線程進入到“運行狀態”)。即時這個“其他線程”與當前調用yield()的線程具有相同的優先級。

7.1.3 yield()和wait()比較

  • wait()的作用是讓當前線程由“運行狀態”進入“阻塞狀態”,而yield()是讓當前線程由“運行狀態”進入“就緒狀態”
  • wait()是會讓線程釋放它所持有的對象的同步鎖,而yield()方法不會釋放對象的同步鎖。

7.2 線程休眠

7.2.1 概述

  • sleep()方法定義在Thread類中,sleep()的作用是讓當前線程休眠,即當前線程會從“遠程狀態”進入到“休眠(阻塞)狀態”
  • sleep()會指定休眠時間,線程休眠的時間會大于/等于該休眠時間
  • 在線程重新被喚醒時,它會由“阻塞狀態”變成“就緒狀態”,從而等待CPU的調度執行。

7.2.2 sleep() 和 wait()的比較

  • wait()的作用是讓當前的線程由“運行狀態”進入到“等待(阻塞)狀態”的同時,也會釋放同步鎖- 但是sleep()的作用是讓當前線程由“運行狀態”進入到“休眠(阻塞)”狀態,但不會釋放鎖。

8. 加入一個線程

8.1 概述

  • 在一個線程T上調用另一個線程t的 join() 方法,相當于在T中加入線程t,要等t結束后(即t.isAlive為假), join() 后面的代碼塊才會執行。
  • 可以在調用jion()時帶上一個超時參數(單位可以是毫秒,或者納秒),這樣如果目標線程在這段時間到期時還沒有結束的話,join()方法總能返回

9. 終止一個線程

9.1 概述

  • interrupt()并不會終止處于“運行狀態”的線程,它會將線程的中斷標記設為true。
  • 綜合線程處于“阻塞狀態”和“運行狀態”的終止方式,比較通用的終止線程的形式如下:
@Override
public void run() {
    try {
        // 1. isInterrupted()保證,只要中斷標記為true就終止線程。
        while (!isInterrupted()) {
            // 執行任務...
        }
    } catch (InterruptedException ie) {  
        // 2. InterruptedException異常保證,當InterruptedException異常產生時,線程被終止。
    }
}

9.2 實例

public class InterruptBlock {

    /**
     * @param args
     */
    public static void main(String[] args) {
    
        class MyThread extends Thread{
            public MyThread(String name){
                super(name);
            }
            
            @Override
            public void run() {    
                try {
                    int i=0;
                    while(!isInterrupted()){
                         Thread.sleep(100);
                         i++;
                         System.out.println(Thread.currentThread().getName()+ " ("+this.getState()+") loop "+i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()+ " ("+this.getState()+") catch InterruptedExecption");
                }    
            }
        }
        
        
        try {
            
            //新建
            Thread t1 = new MyThread("t1");
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is new.");
            
            System.out.println("luo1:"+t1.isInterrupted());
            //啟動
            t1.start();
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is started.");
            System.out.println("luo2:"+t1.isInterrupted());
            //主線程休眠300ms,然后主線程給t1發“中斷”指令
            Thread.sleep(300);
            t1.interrupt();
            System.out.println("luo3:"+t1.isInterrupted());
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is interrupted.");
            
            //主線程休眠300ms,然后查看t1的狀態
            Thread.sleep(300);
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is interrupted now .");
            
            
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}

運行結果:

t1 (NEW ) is new.
luo1:false
t1 (RUNNABLE ) is started.
luo2:false
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
luo3:true
t1 (RUNNABLE) loop 3
t1 (RUNNABLE ) is interrupted.
t1 (TERMINATED ) is interrupted now .

9.3 interrupt()和isInterrupted()的區別

  • interrupt()和isInterrupted()都能夠用于檢測對象的“中斷標記”。區別是:interrupt()除了返回中斷標記之外,它還會清除中斷標記(即將中斷標記設為false);而isInterrupted()僅僅返回中斷標記。

線程進階

1. 線程池

  • 示例
package com.ljw.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolDemo {
 
    public static void main(String[] args) { // 主線程
        // 線程池 ---> Executors工具類(工廠類)
        /*
         * newFixedThreadPool(int threadCount) 創建固定數量的線程池
         * newCachedThreadPool() 創建動態數量的線程池
         */
        ExecutorService es = Executors.newFixedThreadPool(3);
        
        Runnable task = new MyTask();
        
        // 提交任務
        es.submit(task); 
        es.submit(task);
        
        es.shutdown(); // 關閉線程池,則表示不在接收新任務,不代表正在線程池的任務會停掉
    }    
}

class MyTask implements Runnable{

    @Override
    public void run() {
        for(int i=0;i<100;i++) {
            System.out.println(Thread.currentThread().getName()+" MyTask "+i);
        }
    }
}

2. 線程安全與鎖

2.1 重入鎖和讀寫鎖

package com.ljw.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

/**
 * ReentrantLock類,重入鎖:Lock接口的實現類,與synchronized一樣具有互斥鎖功能 lock() 和 unlock()
 * ReentrantReadWriteLock類,讀寫鎖:一種支持一寫多讀的同步鎖,讀寫分離,分別分配讀鎖和寫鎖,在讀操作遠遠高于寫操作的環境中可以提高效率
 *         互斥規則:
 *             寫--寫:互斥,阻塞
 *             讀--寫:互斥,阻塞
 *             讀--讀:不互斥,不阻塞
 *
 */

public class LockDemo {

    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(20);
        Student s = new Student();
//        ReentrantLock rLock = new ReentrantLock(); // 用ReenTrantLock加鎖運行時間20008ms
        ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); // 用讀寫鎖分別對讀寫任務加鎖運行時間3003ms
        ReadLock rl = rwLock.readLock();
        WriteLock wl = rwLock.writeLock();
        
        // 寫任務
        Callable writeTask = new Callable() {

            @Override
            public Object call() throws Exception {
//                rLock.lock();
                wl.lock();
                try {
                    Thread.sleep(1000);
                    s.setValue(100);
                }finally {
//                    rLock.unlock();
                    wl.unlock();
                }
                
                return null;
            }};
        
        // 讀任務
        Callable readTask = new Callable() {

            @Override
            public Object call() throws Exception {
//                rLock.lock();
                rl.lock();
                try {
                    Thread.sleep(1000);
                    s.getValue();
                }finally {
//                    rLock.unlock();
                    rl.unlock();
                }                
                return null;
            }};

        // 開始時間
        long start = System.currentTimeMillis();
        for(int i=0;i<2;i++) { // 寫任務執行 2 次
            es.submit(writeTask);
        }
        for(int i=0;i<18;i++) { // 讀任務執行 18 次
            es.submit(readTask);
        }
        
        es.shutdown(); // 停止線程池,不在接受新的任務,將現有任務全部執行完畢
        
        while(true) {
            if(es.isTerminated()) { // 當線程池中所有任務執行完畢,返回true,否則返回false
                break;
            }
        }
        
        // 執行到這里,說明線程池中所有任務都執行完畢,可以計算結束時間
        System.out.println(System.currentTimeMillis()-start);
    
    }
}

class Student {
    private int value;
    
    //讀
    public int getValue() {
        return value;
    }
    
    //寫
    public void setValue(int value) {
        this.value = value;
    }
}

2.2 線程安全

2.2.1 Collections工具類

  • Collections工具類中提供了多個可以獲得線程安全集合的方法
static  Collection synchronizedCollection(Collection c) 
    //返回由指定集合支持的同步(線程安全)集合。  
static  List synchronizedList(List list) 
    //返回由指定列表支持的同步(線程安全)列表。  
static  Map synchronizedMap(Map m) 
    //返回由指定地圖支持的同步(線程安全)映射。  
static  NavigableMap synchronizedNavigableMap(NavigableMap m) 
    //返回由指定的可導航地圖支持的同步(線程安全)可導航地圖。  
static  NavigableSet synchronizedNavigableSet(NavigableSet s) 
    //返回由指定的可導航集支持的同步(線程安全)可導航集。  
static  Set synchronizedSet(Set s) 
    //返回由指定集合支持的同步(線程安全)集。  
static  SortedMap synchronizedSortedMap(SortedMap m) 
    //返回由指定的排序映射支持的同步(線程安全)排序映射。  
static  SortedSet synchronizedSortedSet(SortedSet s) 
     //返回由指定的排序集支持的同步(線程安全)排序集。,v>,v>,v>,v>,v>,v>,v>,v>,v>

2.2.2 CopyOnWriteArrayList

  • 線程安全的ArrayList
  • 讀寫分離,寫加鎖,讀沒鎖,讀寫之間不互斥
  • 使用方法與ArrayList無異

2.2.3 CopyOnWriteArraySet

  • 基于 CopyOnWriteArrayList

2.2.4 ConcurrentHashMap

  • 初始容量默認為16段(Segment),采用分段鎖設計
  • 不對整個Map加鎖,只對每個Segment加鎖
  • 當多個對象訪問同個Segment才會互斥

審核編輯 黃昊宇
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2973

    瀏覽量

    104911
  • 數據庫
    +關注

    關注

    7

    文章

    3841

    瀏覽量

    64545
  • 人工智能
    +關注

    關注

    1792

    文章

    47514

    瀏覽量

    239247
  • python
    +關注

    關注

    56

    文章

    4801

    瀏覽量

    84878
收藏 人收藏

    評論

    相關推薦

    Java 23功能介紹

    Java 23 包含全新和更新的 Java 語言功能、核心 API 以及 JVM,同時適合新的 Java 開發者和高級開發者。從?IntelliJ IDEA 2024.2?開始已支持 Java
    的頭像 發表于 12-04 10:02 ?292次閱讀
    <b class='flag-5'>Java</b> 23功能介紹

    Java集合API的改進介紹

    解答這些問題。 我們將逐步學習 Java 集合類的優化過程,并按版本逐一對比分析。主要討論的焦點將包括 JDK 1.0、1.2、1.4、1.5、1.6、1.8、9、10、11 和 21 版本的 Java 集合功能
    的頭像 發表于 11-22 11:12 ?234次閱讀
    <b class='flag-5'>Java</b>集合API的改進介紹

    socket 多線程編程實現方法

    在現代網絡編程中,多線程技術被廣泛應用于提高服務器的并發處理能力。Socket編程是網絡通信的基礎,而將多線程技術應用于Socket編程,可以顯著提升服務器的性能。 多線程編程的基本概念 多
    的頭像 發表于 11-12 14:16 ?420次閱讀

    Java中時間戳的使用

    Java中時間戳的使用
    的頭像 發表于 11-06 16:04 ?239次閱讀
    <b class='flag-5'>Java</b>中時間戳的使用

    CPU線程和程序線程的區別

    CPU的線程與程序的線程在概念、作用、實現方式以及性能影響等方面存在顯著差異。以下是對兩者區別的詳細闡述,旨在深入探討這一技術話題。
    的頭像 發表于 09-02 11:18 ?1107次閱讀

    華納云:java web和java有什么區別java web和java有什么區別

    Java Web和Java是兩個不同的概念,它們在功能、用途和實現方式上存在一些區別,下面將詳細介紹它們之間的區別。 1. 功能和用途: – Java是一種編程語言,它提供了一種用于開發各種應用程序
    的頭像 發表于 07-16 13:35 ?852次閱讀
    華納云:<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別<b class='flag-5'>java</b> web和<b class='flag-5'>java</b>有什么區別

    從多線程設計模式到對 CompletableFuture 的應用

    最近在開發 延保服務 頻道頁時,為了提高查詢效率,使用到了多線程技術。為了對多線程方案設計有更加充分的了解,在業余時間讀完了《圖解 Java線程設計模式》這本書,覺得收獲良多。本篇
    的頭像 發表于 06-26 14:18 ?385次閱讀
    從多<b class='flag-5'>線程</b>設計模式到對 CompletableFuture 的應用

    探索虛擬線程:原理與實現

    虛擬線程的引入與優勢 在Loom項目之前,Java虛擬機(JVM)中的線程是通過java.lang.Thread類型來實現的,這些線程被稱為
    的頭像 發表于 06-24 11:35 ?328次閱讀
    探索虛擬<b class='flag-5'>線程</b>:原理與實現

    鴻蒙開發:【線程模型】

    管理其他線程的ArkTS引擎實例,例如使用TaskPool(任務池)創建任務或取消任務、啟動和終止Worker線程。
    的頭像 發表于 06-13 16:38 ?434次閱讀
    鴻蒙開發:【<b class='flag-5'>線程</b>模型】

    動態線程池思想學習及實踐

    相關文檔 美團線程池實踐:https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html 線程池思想解析:https
    的頭像 發表于 06-13 15:43 ?1217次閱讀
    動態<b class='flag-5'>線程</b>池思想<b class='flag-5'>學習</b>及實踐

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序中包含了兩個或以上的線程,每個線程都可以并行執行不同的任務或操作。
    的頭像 發表于 03-14 16:55 ?765次閱讀

    python中5種線程鎖盤點

    線程安全是多線程或多進程編程中的一個概念,在擁有共享數據的多條線程并行執行的程序中,線程安全的代碼會通過同步機制保證各個線程都可以正常且正確
    發表于 03-07 11:08 ?1643次閱讀
    python中5種<b class='flag-5'>線程</b>鎖盤點

    什么是動態線程池?動態線程池的簡單實現思路

    因此,動態可監控線程池一種針對以上痛點開發的線程池管理工具。主要可實現功能有:提供對 Spring 應用內線程池實例的全局管控、應用運行時動態變更線程池參數以及
    的頭像 發表于 02-28 10:42 ?677次閱讀

    linux多線程編程實例

    linux線程
    的頭像 發表于 02-15 21:16 ?497次閱讀
    linux多<b class='flag-5'>線程</b>編程實例

    線程是什么的基本單位 進程與線程的本質區別

    線程是操作系統中處理器調度的基本單位,它代表著獨立的執行流。在一個進程中,可以包含多個線程,這些線程共享相同的進程資源,如內存空間、文件描述符等。 進程是操作系統中運行的程序的實例,它包含了程序
    的頭像 發表于 02-02 16:30 ?979次閱讀
    主站蜘蛛池模板: 77成人| 97久久综合九色综合| 高清成年美女黄网站色大| 人人玩人人添天天爽| 久久九色| 天天摸天天躁天天添天天爽| 狠狠做深爱婷婷综合一区| 色色色色色色色色色色色| 泰国一级毛片aaa下面毛多| 激情九月| 亚洲影视大全| 五月开心六月伊人色婷婷| 中文天堂最新版资源新版天堂资源| 国产一区二区中文字幕| 亚洲国产欧美在线成人aaaa| 男女一进一出抽搐免费视频| 国产在线欧美精品卡通动漫| 亚洲久优优色优在线播放| 亚洲精品中文字幕乱码三区一二| 同性男男肉交短文| 黄色高清视频网站| 福利观看| 一区二区三区视频网站| 中文一级黄色片| 三级网站在线| 四虎精品成人a在线观看| 全部在线播放免费毛片| 国产精品成人在线播放| 国模精品视频| 黄色一级视频欧美| 毛色毛片免费观看| 不良视频在线观看| 免费福利午夜影视网| 国模吧双双大尺度炮交gogo| 黄色网址视频在线观看| 69xxx视频hd| 中文字幕一区在线| 伊人伊成久久人综合网777| 亚洲高清色| 欧美城天堂网| 黄色美女网站在线观看|