91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java?Thread多線程開發中Object類怎么使用

發布時間:2023-03-01 10:55:15 來源:億速云 閱讀:120 作者:iii 欄目:開發技術

這篇“Java Thread多線程開發中Object類怎么使用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Java Thread多線程開發中Object類怎么使用”文章吧。


方法概覽

Thread

Java?Thread多線程開發中Object類怎么使用

wait  notify notifyAll方法詳解

作用

阻塞階段

使用了wait方法之后,線程就會進入阻塞階段,只有發生以下四種情況中的其中一個,線程才會被喚醒

  • 另一個線程調用了這個線程的notify方法,剛好喚醒的是本線程

  • 另一個線程調用了這個對象的notifyAll方法

  • 過了wait規定的超時時間

  • 線程調用了interrupt

喚醒階段

notify會喚醒單個處于阻塞狀態的線程,喚醒的線程是隨機的

notify和wait都需要寫在synchronized代碼塊里,不然會拋出異常

notifyAll會喚醒所有等待的線程

遇到中斷

執行wait方法之后,被中斷,會拋出InterruptedException這個異常

代碼展示

  • 展示wait和notify的基本用法

  • 該代碼執行wait方法之后會釋放鎖,然后thread2執行notify方法

  • notify方法執行完畢之后,并沒有立即釋放鎖,而是接著執行之后的代碼,也就是打印“Thread2調用notify”這句話

  • thread2執行完畢之后,會進行釋放鎖,thread1才會繼續執行

  • 在此期間,thread1雖然被喚醒,但是一直在等待thread2同步代碼塊里面的代碼執行完畢

public class Wait {
    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        Thread.sleep(200);
        thread2.start();
    }
    public static Object object = new Object();
    static class Thread1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("Thread1執行");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread1獲取鎖");
            }
        }
    }
    static class Thread2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("Thread2調用notify");
            }
        }
    }
}
/*
Thread1執行
Thread2調用notify
Thread1獲取鎖
* */
  • notify和notifyAll的展示

  • 第一個輸出:threadc調用notifyAll

  • 第二個輸出:threadc調用notify

  • 調用notify的時候,程序并沒有結束,threadb陷入等待

public class notifyOrAll implements Runnable{
    private static final Object a = new Object();
    public static void main(String[] args) throws InterruptedException {
        Runnable r = new notifyOrAll();
        Thread threada = new Thread(r);
        Thread threadb = new Thread(r);
        Thread threadc = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
//                    a.notifyAll();
                    a.notify();
                    System.out.println(Thread.currentThread().getName() + "notify");
                }
            }
        });
        threada.start();
        Thread.sleep(200);
        threadb.start();
        Thread.sleep(200);
        threadc.start();
    }
    @Override
    public void run() {
        synchronized (a) {
            System.out.println(Thread.currentThread().getName() + "得到鎖");
            try {
                System.out.println(Thread.currentThread().getName() + "wait");
                a.wait();
                System.out.println(Thread.currentThread().getName() + "wait結束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
/*
Thread-0得到鎖
Thread-0wait
Thread-1得到鎖
Thread-1wait
Thread-2notifyAll
Thread-1wait結束
Thread-0wait結束
* */
/*
Thread-0得到鎖
Thread-0wait
Thread-1得到鎖
Thread-1wait
Thread-2notify
Thread-0wait結束
* */
  • 只釋放當前monitor

  • 證明wait只釋放當前的那把鎖

public class OwnMonitor {
    private static volatile Object a = new Object();
    private static volatile Object b = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("threadA得到a");
                    synchronized (b) {
                        System.out.println("threadA得到鎖b");

                        try {
                            System.out.println("threadA釋放a");
                            a.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("threadB得到a");
                    System.out.println("threadB要獲取b");
                    synchronized (b) {
                        System.out.println("threadB得到b");
                    }
                }
            }
        });
        threadA.start();
        Thread.sleep(1000);
        threadB.start();
    }
}
/*
threadA得到a
threadA得到鎖b
threadA釋放a
threadB得到a
threadB要獲取b
* */

特點

  • 執行這些方法必須先獲取鎖

  • notify只能換取一個,而且是隨機的

  • 都屬于Object。任何對象都可以調用

  • 都是native final修飾的

當線程從wait狀態剛被喚醒時,通常不能直接得到鎖,那就會從waiting狀態轉換到blocked狀態,搶到鎖之后狀態轉變為runnable

如果發生異常,則直接跳到Terminated狀態

通過wait notify方法實現生產者和消費者

  • 將storge當作生產者和消費者進行工作的倉庫

  • 如果storge中沒有數據,生產者就開始wait

  • 如果storge中數據滿了,消費者就開始wait

  • 生產者和消費者每進行一次生產和消費,就執行notify

public class ProducerConsumer {
    public static void main(String[] args) {
        Storge storge = new Storge();
        Producer producer = new Producer(storge);
        Consumer consumer = new Consumer(storge);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}
class Producer implements Runnable {
    private Storge storge;
    public Producer(Storge storge) {
        this.storge = storge;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storge.put();
        }
    }
}
class Consumer implements Runnable {
    private Storge storge;
    public Consumer(Storge storge) {
        this.storge = storge;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storge.take();
        }
    }
}
class Storge {
    private int maxSize;
    private LinkedList<Date> storge;
    public Storge() {
        maxSize = 10;
        storge = new LinkedList<>();
    }
    public synchronized void put() {
        while (storge.size() == maxSize) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        storge.add(new Date());
        System.out.println("已經有了" + storge.size());
        notify();
    }
    public synchronized void take() {
        while (storge.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("拿到了" + storge.poll() + "還剩" + storge.size());
        notify();
    }
}

sleep方法詳解

作用:讓線程在預期的時間執行,其他時間不占用CPU資源

特點:和wait不一樣,sleep不釋放鎖

sleep不會釋放鎖

證明sleep不會釋放 synchronized鎖

public class SleepSyn implements Runnable{
    public static void main(String[] args) {
        SleepSyn sleepSyn = new SleepSyn();
        new Thread(sleepSyn).start();
        new Thread(sleepSyn).start();
    }
    @Override
    public void run() {
        syn();
    }
    private synchronized void syn() {
        System.out.println(Thread.currentThread().getName() + "獲取鎖");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "釋放鎖");
    }
}
/*
* Thread-0獲取鎖
Thread-0釋放鎖
Thread-1獲取鎖
Thread-1釋放鎖
* */

證明sleep不釋放Lock鎖

public class sleepLock implements Runnable{
    private static final Lock LOCK = new ReentrantLock();
    @Override
    public void run() {
        LOCK.lock();
        System.out.println(Thread.currentThread().getName() + "獲取鎖");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            LOCK.unlock();
        }
        System.out.println(Thread.currentThread().getName() + "釋放鎖");
    }
    public static void main(String[] args) {
        sleepLock sleepLock = new sleepLock();
        new Thread(sleepLock).start();
        new Thread(sleepLock).start();
    }
}
/*
* Thread-0獲取鎖
Thread-0釋放鎖
Thread-1獲取鎖
Thread-1釋放鎖
* */

sleep響應中斷

  • 拋出InterruptedException

  • 會清除中斷狀態

  • 中斷之后,拋出異常繼續執行

public class sleepInterrupted implements Runnable{
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new sleepInterrupted());
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(new Date());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("中斷");
                e.printStackTrace();
            }
        }
    }
}
/*
* Fri Jan 27 21:11:57 CST 2023
Fri Jan 27 21:11:58 CST 2023
中斷
Fri Jan 27 21:11:59 CST 2023
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at java.lang.Thread.sleep(Thread.java:340)
   at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
   at com.jx.JavaTest.ThreadObjectMethod.sleepInterrupted.run(sleepInterrupted.java:21)
   at java.lang.Thread.run(Thread.java:748)
Fri Jan 27 21:12:00 CST 2023
Fri Jan 27 21:12:01 CST 2023
Fri Jan 27 21:12:02 CST 2023
Fri Jan 27 21:12:03 CST 2023
Fri Jan 27 21:12:04 CST 2023
Fri Jan 27 21:12:05 CST 2023
Fri Jan 27 21:12:06 CST 2023
Process finished with exit code 0
* */

總結

sleep方法可以讓線程進入waiting狀態,不占用CPU資源,但是不釋放鎖,規定時間之后再運行

休眠期間如果被打斷,會拋出異常并清除中斷狀態

join方法詳解

新線程加入,主線程等子線程執行完畢

代碼展示

  • 前一個結果是使用join

  • 后一個結果是沒使用join

  • 可知使用join之后,主線程會等join的線程執行完畢再繼續執行

public class join {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "執行完畢");
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "執行完畢");
            }
        });
        thread1.start();
        thread2.start();
        System.out.println("開始等待子線程運行");
//        thread1.join();
//        thread2.join();
        System.out.println("所有線程執行完畢");
    }
}
/*
* 開始等待子線程運行
Thread-0執行完畢
Thread-1執行完畢
所有線程執行完畢
* */
/*
* 開始等待子線程運行
所有線程執行完畢
Thread-1執行完畢
Thread-0執行完畢
* */
  • 遇到中斷

  • 第一個的運行結果是主線程沒中斷的打印結果

  • 第二個的運行結果是join期間進行中斷的打印結果,可知在打印了“子線程運行完畢”之后,依然打印了“啟動”兩個字,可知會造成運行混亂

  • 可以在捕獲異常的代碼塊中,將join的線程也中斷,可以解決上面的問題

public class joinInterrupt {
    public static void main(String[] args) {
        Thread main1 = Thread.currentThread();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    main1.interrupt();
                    Thread.sleep(2000);
                    System.out.println("啟動");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.start();
        System.out.println("join");
        try {
            thread1.join();
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "中斷");
            // thread1.interrupt();
            e.printStackTrace();
        }
        System.out.println("子線程運行完畢");
    }
}
/*
* join
啟動
子線程運行完畢
* */
/*
* join
main中斷
子線程運行完畢
java.lang.InterruptedException
   at java.lang.Object.wait(Native Method)
   at java.lang.Thread.join(Thread.java:1252)
   at java.lang.Thread.join(Thread.java:1326)
   at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
啟動
Process finished with exit code 0
* */
/*
* join
main中斷
子線程運行完畢
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt$1.run(joinInterrupt.java:13)
   at java.lang.Thread.run(Thread.java:748)
java.lang.InterruptedException
   at java.lang.Object.wait(Native Method)
   at java.lang.Thread.join(Thread.java:1252)
   at java.lang.Thread.join(Thread.java:1326)
   at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
Process finished with exit code 0
* */

join期間,線程處于WAITING狀態

public class joinStates {
    public static void main(String[] args) throws InterruptedException {
        Thread main1 = Thread.currentThread();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println(main1.getState());
                    System.out.println("子線程運行結束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        System.out.println("join");
        thread.join();
        System.out.println("運行完畢");
    }
}
/*
* join
WAITING
子線程運行結束
運行完畢
* */

yield方法

用來釋放CPU時間片,但是不一定能達到預期的效果,因為有時CPU資源不緊張,無需yield

和sleep的區別是:sleep期間不會被再次調度但是yield會立刻處于競爭狀態,還會隨時再次被調度

以上就是關于“Java Thread多線程開發中Object類怎么使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

昂仁县| 荣昌县| 道孚县| 农安县| 华池县| 石嘴山市| SHOW| 西和县| 昌宁县| 道孚县| 济源市| 武冈市| 永春县| 富蕴县| 崇信县| 吉水县| 藁城市| 宜昌市| 陵水| 乳山市| 马关县| 东乌珠穆沁旗| 吉木萨尔县| 梧州市| 神木县| 乌什县| 木兰县| 青浦区| 汶上县| 舒兰市| 江山市| 卢氏县| 奉新县| 建湖县| 滦平县| 阿坝| 新兴县| 武陟县| 巩义市| 崇明县| 特克斯县|