91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Java線程學(xué)習(xí)基礎(chǔ)詳解

電子設(shè)計(jì) ? 來源:電子設(shè)計(jì) ? 作者:電子設(shè)計(jì) ? 2020-12-10 22:02 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

線程基礎(chǔ)

1. 線程的生命周期

1.1 新建狀態(tài):

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

1.2 就緒狀態(tài):

  • 當(dāng)線程對(duì)象調(diào)用了start()方法之后,該線程就進(jìn)入就緒狀態(tài)。就緒狀態(tài)的線程處于就緒隊(duì)列中,要等待JVM里線程調(diào)度器的調(diào)度。

1.3 運(yùn)行狀態(tài):

  • 如果就緒狀態(tài)的線程獲取 CPU 資源,就可以執(zhí)行 run(),此時(shí)線程便處于運(yùn)行狀態(tài)。處于運(yùn)行狀態(tài)的線程最為復(fù)雜,它可以變?yōu)樽枞麪顟B(tài)、就緒狀態(tài)和死亡狀態(tài)。

1.4 阻塞狀態(tài):

  • 如果一個(gè)線程執(zhí)行了sleep(睡眠)、suspend(掛起)等方法,失去所占用資源之后,該線程就從運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài)。在睡眠時(shí)間已到或獲得設(shè)備資源后可以重新進(jìn)入就緒狀態(tài)??梢苑譃槿N:

    • 等待阻塞:運(yùn)行狀態(tài)中的線程執(zhí)行 wait() 方法,使線程進(jìn)入到等待阻塞狀態(tài)。
    • 同步阻塞:線程在獲取 synchronized 同步鎖失敗(因?yàn)橥芥i被其他線程占用)。
    • 其他阻塞:通過調(diào)用線程的 sleep() 或 join() 發(fā)出了 I/O 請(qǐng)求時(shí),線程就會(huì)進(jìn)入到阻塞狀態(tài)。當(dāng)sleep() 狀態(tài)超時(shí),join() 等待線程終止或超時(shí),或者 I/O 處理完畢,線程重新轉(zhuǎn)入就緒狀態(tài)。

1.5 死亡狀態(tài):

  • 一個(gè)運(yùn)行狀態(tài)的線程完成任務(wù)或者其他終止條件發(fā)生時(shí),該線程就切換到終止?fàn)顟B(tài)。

2. 線程的優(yōu)先級(jí)和守護(hù)線程

2.1 線程的優(yōu)先級(jí)

  • 每一個(gè) Java 線程都有一個(gè)優(yōu)先級(jí),這樣有助于操作系統(tǒng)確定線程的調(diào)度順序。
  • Java 線程的優(yōu)先級(jí)是一個(gè)整數(shù),其取值范圍是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
  • 默認(rèn)情況下,每一個(gè)線程都會(huì)分配一個(gè)優(yōu)先級(jí) NORM_PRIORITY(5)。

2.2 守護(hù)線程

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

3. 創(chuàng)建線程

3.1 通過實(shí)現(xiàn) Runnable 接口

  • 步驟:

    • 創(chuàng)建類實(shí)現(xiàn) Runnable 接口
    • 實(shí)現(xiàn) run() 方法,線程實(shí)際運(yùn)行的方法
    • 實(shí)現(xiàn) start() 方法,里面實(shí)例化線程對(duì)象(new Thread(this, threadName)),調(diào)用線程對(duì)象的 start() 方法
  • 代碼實(shí)現(xiàn)

    package com.ljw.thread;
    
    public class RunnableDemo {
    
        public static void main(String[] args) {
            // 測(cè)試
            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("創(chuàng)建線程 "+threadName);
            }
    
            
            @Override
            public void run() {
                System.out.println("正在運(yùn)行線程:"+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 類本身

  • 步驟:

    • 創(chuàng)建類繼承 Thread 類
    • 下面與用Runnable接口一樣

3.3 通過 Callable 和 Future 創(chuàng)建線程

  • 步驟:

    • 創(chuàng)建 Callable 接口的實(shí)現(xiàn)類,并實(shí)現(xiàn) call() 方法,該 call() 方法將作為線程執(zhí)行體,并且有返回值。
    • 創(chuàng)建 Callable 實(shí)現(xiàn)類的實(shí)例,使用 FutureTask 類來包裝 Callable 對(duì)象,該 FutureTask 對(duì)象封裝了該 Callable 對(duì)象的 call() 方法的返回值。
    • 使用 FutureTask 對(duì)象作為 Thread 對(duì)象的 target 創(chuàng)建并啟動(dòng)新線程。
    • 調(diào)用 FutureTask 對(duì)象的 get() 方法來獲得子線程執(zhí)行結(jié)束后的返回值。
  • Callable接口與Runnable接口的區(qū)別:

    • Callable中call方法可以有返回值,而Runnable中的run方法沒有返回值
  • 代碼實(shí)現(xiàn)

    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()+" 的循環(huán)變量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關(guān)鍵字

4.1 概述

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

4.2 基本原則

  • 第一條:當(dāng)一個(gè)線程訪問某對(duì)象的synchronized方法或者synchronized代碼塊時(shí),其他線程對(duì)該對(duì)象的該synchronized方法或者synchronized代碼塊的訪問將被阻塞。
  • 第二條:當(dāng)一個(gè)線程訪問某對(duì)象的synchronized方法或者synchronized代碼塊時(shí),其他線程仍然可以訪問該對(duì)象的非同步代碼塊。
  • 第三條:當(dāng)一個(gè)線程訪問某對(duì)象的synchronized方法或者synchronized代碼塊時(shí),其他線程對(duì)該對(duì)象的其他的synchronized方法或者synchronized代碼塊的訪問將被阻塞。

4.3 實(shí)例

  • 兩個(gè)相似的例子

    • 實(shí)例1:實(shí)現(xiàn)接口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() + " 正在進(jìn)行打印 " +i);
                        }
                    }
                }
            }
            
            Runnable runnable = new MyRunnable();
            Thread t1 = new Thread(runnable,"t1");
            Thread t2 = new Thread(runnable,"t2");
            
            t1.start();
            t2.start();
        }
    }

    運(yùn)行結(jié)果:

    t1 正在進(jìn)行打印 0
    t1 正在進(jìn)行打印 1
    t1 正在進(jìn)行打印 2
    t1 正在進(jìn)行打印 3
    t1 正在進(jìn)行打印 4
    t2 正在進(jìn)行打印 0
    t2 正在進(jìn)行打印 1
    t2 正在進(jìn)行打印 2
    t2 正在進(jìn)行打印 3
    t2 正在進(jìn)行打印 4

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

    • 實(shí)例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()+" 正在進(jìn)行打印 "+i);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
            Thread t1 = new MyThread("t1");
            Thread t2 = new MyThread("t2");
            t1.start();
            t2.start();
        }
    }

    運(yùn)行結(jié)果:

    t2 正在進(jìn)行打印 0
    t1 正在進(jìn)行打印 0
    t2 正在進(jìn)行打印 1
    t1 正在進(jìn)行打印 1
    t1 正在進(jìn)行打印 2
    t2 正在進(jìn)行打印 2
    t2 正在進(jìn)行打印 3
    t1 正在進(jìn)行打印 3
    t1 正在進(jìn)行打印 4
    t2 正在進(jìn)行打印 4

    對(duì)比結(jié)果:發(fā)現(xiàn)實(shí)例1的兩個(gè)線程是一個(gè)結(jié)束后,另一個(gè)才運(yùn)行,實(shí)例2的是交叉運(yùn)行,在run()方法中都有synchronized(this),為什么結(jié)果不一樣?

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

4.4 synchronized方法和synchronized代碼塊

4.4.1 概述

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

4.4.2 實(shí)例

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 實(shí)例鎖和全局鎖

4.5.1 概述

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

4.5.2 實(shí)例

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

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

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

    • 不能同時(shí)訪問,因?yàn)槎际窃L問對(duì)象x的同步鎖
  • x.isSyncA()與y.isSyncA()

    • 可以同時(shí)訪問,因?yàn)槭窃L問不同對(duì)象(x和y)的同步鎖
  • x.cSyncA()與y.cSyncB()

    • 不能同時(shí)訪問,因?yàn)閮蓚€(gè)方法是靜態(tài)的,相當(dāng)于用Something.cSyncA()和Something.cSyncB()訪問,是相同的對(duì)象
  • x.isSyncA()與Something.cSyncA()

    • 可以同時(shí)訪問,因?yàn)樵L問不同對(duì)象

5. Volatile 關(guān)鍵字

5.1 Volatile原理

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

6. 線程等待和喚醒

6.1 常用方法

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

6.2 實(shí)例

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("開始運(yùn)行線程 "+Thread.currentThread().getName());
                    System.out.println("喚醒線程notify()");
                    notify();
                }
            }
        }
        
        ThreadTest thread1 = new ThreadTest();
        thread1.start();
        
        synchronized (thread1) {
            try {
                System.out.println("主線程進(jìn)入阻塞,釋放thread對(duì)象的同步鎖,wait()");
                thread1.wait(); // wait()是讓當(dāng)前線程進(jìn)入阻塞狀態(tài),wait()是在主線程中執(zhí)行,
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("主線程繼續(xù)進(jìn)行");
    }
}

7. 線程讓步和休眠

7.1 線程讓步

7.1.1 概述

  • 在Java線程中,yield()方法的作用是讓步,它能讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入到“就緒狀態(tài)”,可能讓其它同級(jí)別的線程獲得執(zhí)行權(quán),但不一定,可能它自己再次由“就緒狀態(tài)”進(jìn)入到“運(yùn)行狀態(tài)”

7.1.2 實(shí)例

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();
    }
}

運(yùn)行結(jié)果(不唯一):

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

結(jié)果說明:
線程t1在能被2整除的時(shí)候,并不一定切換到線程2。這表明,yield()方法雖然可以讓線程由“運(yùn)行狀態(tài)”進(jìn)入到“就緒狀態(tài)”;但是,它不一定會(huì)讓其他線程獲取CPU執(zhí)行權(quán)(其他線程進(jìn)入到“運(yùn)行狀態(tài)”)。即時(shí)這個(gè)“其他線程”與當(dāng)前調(diào)用yield()的線程具有相同的優(yōu)先級(jí)。

7.1.3 yield()和wait()比較

  • wait()的作用是讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入“阻塞狀態(tài)”,而yield()是讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入“就緒狀態(tài)”
  • wait()是會(huì)讓線程釋放它所持有的對(duì)象的同步鎖,而yield()方法不會(huì)釋放對(duì)象的同步鎖。

7.2 線程休眠

7.2.1 概述

  • sleep()方法定義在Thread類中,sleep()的作用是讓當(dāng)前線程休眠,即當(dāng)前線程會(huì)從“遠(yuǎn)程狀態(tài)”進(jìn)入到“休眠(阻塞)狀態(tài)”
  • sleep()會(huì)指定休眠時(shí)間,線程休眠的時(shí)間會(huì)大于/等于該休眠時(shí)間
  • 在線程重新被喚醒時(shí),它會(huì)由“阻塞狀態(tài)”變成“就緒狀態(tài)”,從而等待CPU的調(diào)度執(zhí)行。

7.2.2 sleep() 和 wait()的比較

  • wait()的作用是讓當(dāng)前的線程由“運(yùn)行狀態(tài)”進(jìn)入到“等待(阻塞)狀態(tài)”的同時(shí),也會(huì)釋放同步鎖- 但是sleep()的作用是讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入到“休眠(阻塞)”狀態(tài),但不會(huì)釋放鎖。

8. 加入一個(gè)線程

8.1 概述

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

9. 終止一個(gè)線程

9.1 概述

  • interrupt()并不會(huì)終止處于“運(yùn)行狀態(tài)”的線程,它會(huì)將線程的中斷標(biāo)記設(shè)為true。
  • 綜合線程處于“阻塞狀態(tài)”和“運(yùn)行狀態(tài)”的終止方式,比較通用的終止線程的形式如下:
@Override
public void run() {
    try {
        // 1. isInterrupted()保證,只要中斷標(biāo)記為true就終止線程。
        while (!isInterrupted()) {
            // 執(zhí)行任務(wù)...
        }
    } catch (InterruptedException ie) {  
        // 2. InterruptedException異常保證,當(dāng)InterruptedException異常產(chǎn)生時(shí),線程被終止。
    }
}

9.2 實(shí)例

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());
            //啟動(dòng)
            t1.start();
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is started.");
            System.out.println("luo2:"+t1.isInterrupted());
            //主線程休眠300ms,然后主線程給t1發(fā)“中斷”指令
            Thread.sleep(300);
            t1.interrupt();
            System.out.println("luo3:"+t1.isInterrupted());
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is interrupted.");
            
            //主線程休眠300ms,然后查看t1的狀態(tài)
            Thread.sleep(300);
            System.out.println(t1.getName()+" ("+t1.getState()+" ) is interrupted now .");
            
            
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}

運(yùn)行結(jié)果:

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()的區(qū)別

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

線程進(jìn)階

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) 創(chuàng)建固定數(shù)量的線程池
         * newCachedThreadPool() 創(chuàng)建動(dòng)態(tài)數(shù)量的線程池
         */
        ExecutorService es = Executors.newFixedThreadPool(3);
        
        Runnable task = new MyTask();
        
        // 提交任務(wù)
        es.submit(task); 
        es.submit(task);
        
        es.shutdown(); // 關(guān)閉線程池,則表示不在接收新任務(wù),不代表正在線程池的任務(wù)會(huì)停掉
    }    
}

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接口的實(shí)現(xiàn)類,與synchronized一樣具有互斥鎖功能 lock() 和 unlock()
 * ReentrantReadWriteLock類,讀寫鎖:一種支持一寫多讀的同步鎖,讀寫分離,分別分配讀鎖和寫鎖,在讀操作遠(yuǎn)遠(yuǎn)高于寫操作的環(huán)境中可以提高效率
 *         互斥規(guī)則:
 *             寫--寫:互斥,阻塞
 *             讀--寫:互斥,阻塞
 *             讀--讀:不互斥,不阻塞
 *
 */

public class LockDemo {

    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(20);
        Student s = new Student();
//        ReentrantLock rLock = new ReentrantLock(); // 用ReenTrantLock加鎖運(yùn)行時(shí)間20008ms
        ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); // 用讀寫鎖分別對(duì)讀寫任務(wù)加鎖運(yùn)行時(shí)間3003ms
        ReadLock rl = rwLock.readLock();
        WriteLock wl = rwLock.writeLock();
        
        // 寫任務(wù)
        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;
            }};
        
        // 讀任務(wù)
        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;
            }};

        // 開始時(shí)間
        long start = System.currentTimeMillis();
        for(int i=0;i<2;i++) { // 寫任務(wù)執(zhí)行 2 次
            es.submit(writeTask);
        }
        for(int i=0;i<18;i++) { // 讀任務(wù)執(zhí)行 18 次
            es.submit(readTask);
        }
        
        es.shutdown(); // 停止線程池,不在接受新的任務(wù),將現(xiàn)有任務(wù)全部執(zhí)行完畢
        
        while(true) {
            if(es.isTerminated()) { // 當(dāng)線程池中所有任務(wù)執(zhí)行完畢,返回true,否則返回false
                break;
            }
        }
        
        // 執(zhí)行到這里,說明線程池中所有任務(wù)都執(zhí)行完畢,可以計(jì)算結(jié)束時(shí)間
        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工具類中提供了多個(gè)可以獲得線程安全集合的方法
static  Collection synchronizedCollection(Collection c) 
    //返回由指定集合支持的同步(線程安全)集合。  
static  List synchronizedList(List list) 
    //返回由指定列表支持的同步(線程安全)列表。  
static  Map synchronizedMap(Map m) 
    //返回由指定地圖支持的同步(線程安全)映射。  
static  NavigableMap synchronizedNavigableMap(NavigableMap m) 
    //返回由指定的可導(dǎo)航地圖支持的同步(線程安全)可導(dǎo)航地圖。  
static  NavigableSet synchronizedNavigableSet(NavigableSet s) 
    //返回由指定的可導(dǎo)航集支持的同步(線程安全)可導(dǎo)航集。  
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

  • 初始容量默認(rèn)為16段(Segment),采用分段鎖設(shè)計(jì)
  • 不對(duì)整個(gè)Map加鎖,只對(duì)每個(gè)Segment加鎖
  • 當(dāng)多個(gè)對(duì)象訪問同個(gè)Segment才會(huì)互斥

審核編輯 黃昊宇
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    3001

    瀏覽量

    116449
  • 數(shù)據(jù)庫
    +關(guān)注

    關(guān)注

    7

    文章

    4020

    瀏覽量

    68359
  • 人工智能
    +關(guān)注

    關(guān)注

    1817

    文章

    50099

    瀏覽量

    265444
  • python
    +關(guān)注

    關(guān)注

    57

    文章

    4876

    瀏覽量

    90058
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    摩爾線程正式開源TileLang-MUSA項(xiàng)目

    近日,摩爾線程正式開源TileLang-MUSA項(xiàng)目,實(shí)現(xiàn)對(duì)TileLang編程語言的完整支持。該項(xiàng)目已成功在摩爾線程多代全功能GPU上完成功能驗(yàn)證與特性開發(fā),旨在通過高層抽象與編譯器優(yōu)化,大幅降低開發(fā)門檻,為國產(chǎn)算力平臺(tái)提供更高效的AI與高性能計(jì)算開發(fā)體驗(yàn)。
    的頭像 發(fā)表于 02-11 16:57 ?1265次閱讀

    解析Linux的進(jìn)程、線程和協(xié)程

    系統(tǒng)的穩(wěn)定性和安全性。 (3)創(chuàng)建與銷毀:Linux使用fork()系統(tǒng)調(diào)用來創(chuàng)建新進(jìn)程,通過exit()來終止進(jìn)程。 線程(Thread) 線程是進(jìn)程內(nèi)的執(zhí)行單元,多個(gè)線程共享相同的內(nèi)存空間
    發(fā)表于 12-22 11:00

    線程的系統(tǒng)

    線程系統(tǒng)的事件響應(yīng)也是在中斷中完成的,但事件的處理是在線程中完成的。在多線程系統(tǒng)中,線程跟中斷一樣,也具有優(yōu)先級(jí),優(yōu)先級(jí)高的線程會(huì)被優(yōu)先執(zhí)
    發(fā)表于 12-08 07:55

    摩爾線程發(fā)布Torch-MUSA v2.7.0版本

    近日,摩爾線程正式發(fā)布PyTorch深度學(xué)習(xí)框架的MUSA擴(kuò)展庫——Torch-MUSA v2.7.0,新版本在功能集成、性能優(yōu)化與硬件支持方面實(shí)現(xiàn)進(jìn)一步突破。Torch-MUSA在短短一個(gè)月
    的頭像 發(fā)表于 12-04 09:05 ?1131次閱讀

    Linux多線程對(duì)比單線程的優(yōu)勢(shì)

    在Linux系統(tǒng)中,線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。線程被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)行單位。一個(gè)進(jìn)程可以擁有多個(gè)線程,這些線程共享相同的內(nèi)存空間和系統(tǒng)資源。
    發(fā)表于 12-01 06:11

    Arm Neoverse CPU上大代碼量Java應(yīng)用的性能測(cè)試

    Java 是互聯(lián)網(wǎng)領(lǐng)域廣泛使用的編程語言。Java 應(yīng)用的一些特性使其性能表現(xiàn)與提前編譯的原生應(yīng)用(例如 C 程序)大相徑庭。由于 Java 字節(jié)碼無法直接在 CPU 上執(zhí)行,因此通常運(yùn)行時(shí)在
    的頭像 發(fā)表于 11-05 11:25 ?763次閱讀
    Arm Neoverse CPU上大代碼量<b class='flag-5'>Java</b>應(yīng)用的性能測(cè)試

    Java 25正式發(fā)布,重要特性詳解(附代碼示例):靈活構(gòu)造函數(shù)體、模塊導(dǎo)入聲明、AOT方法分析等

    Java 25現(xiàn)已發(fā)布,更多新特性來了!配合Perforce JRebel,代碼修改即時(shí)生效,無需重啟服務(wù),即可實(shí)現(xiàn)“改完就看效果”。新特性+快工具,讓你的Java開發(fā)體驗(yàn)雙倍提升!
    的頭像 發(fā)表于 10-29 13:16 ?1455次閱讀
    <b class='flag-5'>Java</b> 25正式發(fā)布,重要特性<b class='flag-5'>詳解</b>(附代碼示例):靈活構(gòu)造函數(shù)體、模塊導(dǎo)入聲明、AOT方法分析等

    tcpip線程被mu0鎖住導(dǎo)致網(wǎng)絡(luò)線程無法使用怎么解決?

    各位好,我使用rtthread開發(fā)STM32F407VGT6芯片,程序有多個(gè)線程,每個(gè)線程都會(huì)創(chuàng)建一個(gè)socket,建立tcp連接或者udp連接,現(xiàn)在出現(xiàn)一個(gè)問題,程序長時(shí)間運(yùn)行有概率死機(jī),但是沒有
    發(fā)表于 09-29 06:41

    線程刪除時(shí)遇到斷言,是什么原因?qū)е碌模?/a>

    在一個(gè)線程中調(diào)用線程刪除函數(shù)刪除另外一個(gè)線程,這2個(gè)線程的優(yōu)先級(jí)是相等的,被刪除的線程也是動(dòng)態(tài)創(chuàng)建的,出現(xiàn)了下面的斷言內(nèi)容,一般是什么情況導(dǎo)
    發(fā)表于 09-12 06:08

    Java效率提升指南:5個(gè)Java工具選型建議及Perforce JRebel和XRebel介紹

    企業(yè)級(jí)Java環(huán)境越來越復(fù)雜,真正的破局點(diǎn),可能不在“人”,而在于“工具”。5個(gè)實(shí)用建議,幫你理清Java工具的選型思路。
    的頭像 發(fā)表于 09-11 13:59 ?1504次閱讀
    <b class='flag-5'>Java</b>效率提升指南:5個(gè)<b class='flag-5'>Java</b>工具選型建議及Perforce JRebel和XRebel介紹

    rtth studio中nano 如何創(chuàng)建動(dòng)態(tài)線程?

    有沒有大佬,可以說一下為什么靜態(tài)線程可以正常使用,動(dòng)態(tài)線程怎么也使用不了。 具體需要什么配置才能使用動(dòng)態(tài)線程創(chuàng)建。謝謝!
    發(fā)表于 09-11 06:01

    摩爾線程發(fā)布Torch-MUSA v2.1.1版本

    近日,摩爾線程發(fā)布其面向PyTorch深度學(xué)習(xí)框架的MUSA擴(kuò)展庫——Torch-MUSA v2.1.1。該版本在v2.1.0的基礎(chǔ)上,進(jìn)一步擴(kuò)展了對(duì)大規(guī)模深度學(xué)習(xí)模型訓(xùn)練與推理的支持能力,并在編譯優(yōu)化、計(jì)算性能和算子生態(tài)等方面
    的頭像 發(fā)表于 09-10 11:02 ?1039次閱讀

    線程的安全注意事項(xiàng)

    線程安全是指多個(gè)線程同時(shí)訪問或修改共享資源時(shí),能夠保證程序的正確性和可靠性。 開發(fā)者選擇TaskPool或Worker進(jìn)行多線程開發(fā)時(shí),在TaskPool和Worker的工作線程中導(dǎo)
    發(fā)表于 06-20 07:49

    EtherCAT運(yùn)動(dòng)控制卡應(yīng)用開發(fā)教程之Java

    運(yùn)動(dòng)控制卡的Java開發(fā)及DLL調(diào)用
    的頭像 發(fā)表于 06-13 14:29 ?893次閱讀
    EtherCAT運(yùn)動(dòng)控制卡應(yīng)用開發(fā)教程之<b class='flag-5'>Java</b>

    Java開發(fā)者必備的效率工具——Perforce JRebel是什么?為什么很多Java開發(fā)者在用?

    Perforce JRebel是一款Java開發(fā)效率工具,旨在幫助java開發(fā)人員更快地編寫更好的應(yīng)用程序。JRebel可即時(shí)重新加載對(duì)代碼的修改,無需重啟或重新部署應(yīng)用程序,就能讓開發(fā)者即時(shí)看到代碼更改的效果,從而縮短開發(fā)、調(diào)試和測(cè)試周期,大大提升開發(fā)效率。
    的頭像 發(fā)表于 04-27 13:44 ?860次閱讀
    <b class='flag-5'>Java</b>開發(fā)者必備的效率工具——Perforce JRebel是什么?為什么很多<b class='flag-5'>Java</b>開發(fā)者在用?