<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### Daemon(守護線程) Java 中有兩類線程:User Thread (用戶線程)、Daemon Thread (守護線程) 用戶線程即運行在前臺的線程,而守護線程是運行在后臺的線程。 守護線程作用是為其他前臺線程的運行提供便利服務,而且僅在普通、非守護線程仍然運行時才需要,比如垃圾回收線程就是一個守護線程。當 JVM 檢測僅剩一個守護線程,而用戶線程都已經退出運行時,JVM 就會退出,因為沒有如果沒有了被守護這,也就沒有繼續運行程序的必要了。如果有非守護線程仍然存活,JVM 就不會退出。 守護線程并非只有虛擬機內部提供,用戶在編寫程序時也可以自己設置守護線程。用戶可以用 Thread 的 setDaemon(true) 方法設置當前線程為守護線程。 雖然守護線程可能非常有用,但必須小心確保其他所有非守護線程消亡時,不會由于它的終止而產生任何危害。因為你不可能知道在所有的用戶線程退出運行前,守護線程是否已經完成了預期的服務任務。一旦所有的用戶線程退出了,虛擬機也就退出運行了。 因此,不要在守護線程中執行業務邏輯操作(比如對數據的讀寫等)。 **另外有幾點需要注意:** * setDaemon(true) 必須在調用線程的 start() 方法之前設置,否則會跑出 IllegalThreadStateException 異常。 * 在守護線程中產生的新線程也是守護線程。 * 不要認為所有的應用都可以分配給守護線程來進行服務,比如讀寫操作或者計算邏輯。 守護線程是程序運行時在后臺提供服務的線程,不屬于程序中不可或缺的部分。 當所有非守護線程結束時,程序也就終止,同時會殺死所有守護線程。 main() 屬于非守護線程。 使用 setDaemon() 方法將一個線程設置為守護線程。 ~~~java public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.setDaemon(true); } ~~~ ### sleep() Thread.sleep(millisec) 方法會休眠當前正在執行的線程,millisec 單位為毫秒。 sleep() 可能會拋出 InterruptedException,因為異常不能跨線程傳播回 main() 中,因此必須在本地進行處理。線程中拋出的其它異常也同樣需要在本地進行處理。 ~~~java public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } ~~~ ### [](https://github.com/frank-lam/fullstack-tutorial/blob/master/notes/JavaArchitecture/03-Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B.md#yield)yield() 對靜態方法 Thread.yield() 的調用聲明了**當前線程已經完成了生命周期中最重要的部分**,可以切換給其它線程來執行。該方法只是對線程調度器的一個建議,而且也只是建議具有相同優先級的其它線程可以運行。 ~~~java public void run() { Thread.yield(); } ~~~ ### 線程阻塞 線程可以阻塞于四種狀態: * 當線程執行 Thread.sleep() 時,它一直阻塞到指定的毫秒時間之后,或者阻塞被另一個線程打斷; * 當線程碰到一條 wait() 語句時,它會一直阻塞到接到通知 notify()、被中斷或經過了指定毫秒時間為止(若制定了超時值的話) * 線程阻塞與不同 I/O 的方式有多種。常見的一種方式是 InputStream 的 read() 方法,該方法一直阻塞到從流中讀取一個字節的數據為止,它可以無限阻塞,因此不能指定超時時間; * 線程也可以阻塞等待獲取某個對象鎖的排他性訪問權限(即等待獲得 synchronized 語句必須的鎖時阻塞)。 > 注意,并非所有的阻塞狀態都是可中斷的,以上阻塞狀態的前兩種可以被中斷,后兩種不會對中斷做出反應 <br> ## **中斷** 一個線程執行完畢之后會自動結束,如果在運行過程中發生異常也會提前結束。 ### InterruptedException 通過調用一個線程的 interrupt() 來中斷該線程,如果該線程處于**阻塞、限期等待或者無限期等待**狀態,那么就會拋出 InterruptedException,從而提前結束該線程。但是不能中斷 I/O 阻塞和 synchronized 鎖阻塞。 對于以下代碼,在 main() 中啟動一個線程之后再中斷它,由于線程中調用了 Thread.sleep() 方法,因此會拋出一個 InterruptedException,從而提前結束線程,不執行之后的語句。 ~~~java public class InterruptExample { private static class MyThread1 extends Thread { @Override public void run() { try { Thread.sleep(2000); System.out.println("Thread run"); } catch (InterruptedException e) { e.printStackTrace(); } } } } ~~~ ~~~java public static void main(String[] args) throws InterruptedException { Thread thread1 = new MyThread1(); thread1.start(); thread1.interrupt(); System.out.println("Main run"); } ~~~ ~~~java Main run java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at InterruptExample.lambda$main$0(InterruptExample.java:5) at InterruptExample$$Lambda$1/713338599.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) ~~~ ### interrupted() 如果一個線程的 run() 方法執行一個無限循環,并且沒有執行 sleep() 等會拋出 InterruptedException 的操作,那么調用線程的 interrupt() 方法就無法使線程提前結束。 但是調用 interrupt() 方法會設置線程的中斷標記,此時調用 interrupted() 方法會返回 true。因此可以在循環體中使用 interrupted() 方法來判斷線程是否處于中斷狀態,從而提前結束線程。 ~~~java public class InterruptExample { private static class MyThread2 extends Thread { @Override public void run() { while (!interrupted()) { // .. } System.out.println("Thread end"); } } } ~~~ ~~~js public static void main(String[] args) throws InterruptedException { Thread thread2 = new MyThread2(); thread2.start(); thread2.interrupt(); } ~~~ ~~~ Thread end ~~~ ### Executor 的中斷操作 調用 Executor 的 shutdown() 方法會等待線程都執行完畢之后再關閉,但是如果調用的是 shutdownNow() 方法,則相當于調用每個線程的 interrupt() 方法。 以下使用 Lambda 創建線程,相當于創建了一個匿名內部線程。 ~~~java public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(() -> { try { Thread.sleep(2000); System.out.println("Thread run"); } catch (InterruptedException e) { e.printStackTrace(); } }); executorService.shutdownNow(); System.out.println("Main run"); } ~~~ ~~~java Main run java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at ExecutorInterruptExample.lambda$main$0(ExecutorInterruptExample.java:9) at ExecutorInterruptExample$$Lambda$1/1160460865.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) ~~~ 如果只想中斷 Executor 中的一個線程,可以通過使用 submit() 方法來提交一個線程,它會返回一個 Future 對象,通過調用該對象的 cancel(true) 方法就可以中斷線程。 ~~~java Future<?> future = executorService.submit(() -> { // .. }); future.cancel(true); ~~~ <br> ## 線程之間的協作 當多個線程可以一起工作去解決某個問題時,如果某些部分必須在其它部分之前完成,那么就需要對線程進行協調。 ### join() 在線程中調用另一個線程的 join() 方法,會將當前線程掛起,而不是忙等待,直到目標線程結束。 對于以下代碼,雖然 b 線程先啟動,但是因為在 b 線程中調用了 a 線程的 join() 方法,b 線程會等待 a 線程結束才繼續執行,因此最后能夠保證 a 線程的輸出先于 b 線程的輸出。 ~~~java public class JoinExample { private class A extends Thread { @Override public void run() { System.out.println("A"); } } private class B extends Thread { private A a; B(A a) { this.a = a; } @Override public void run() { try { a.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("B"); } } public void test() { A a = new A(); B b = new B(a); b.start(); a.start(); } } ~~~ ~~~java public static void main(String[] args) { JoinExample example = new JoinExample(); example.test(); } ~~~ ~~~ A B ~~~ ### wait() notify() notifyAll() 調用 wait() 使得線程等待某個條件滿足,線程在等待時會被掛起,當其他線程的運行使得這個條件滿足時,其它線程會調用 notify()(隨機叫醒一個) 或者 notifyAll() (叫醒所有 wait 線程,爭奪時間片的線程只有一個)來喚醒掛起的線程。 它們都屬于 Object 的一部分,而不屬于 Thread。 只能用在**同步方法**或者**同步控制塊**中使用!否則會在運行時拋出 IllegalMonitorStateExeception。 使用 wait() 掛起期間,線程會釋放鎖。這是因為,如果沒有釋放鎖,那么其它線程就無法進入對象的同步方法或者同步控制塊中,那么就無法執行 notify() 或者 notifyAll() 來喚醒掛起的線程,造成死鎖。 ~~~java public class WaitNotifyExample { public synchronized void before() { System.out.println("before"); notifyAll(); } public synchronized void after() { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("after"); } } ~~~ ~~~java public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); WaitNotifyExample example = new WaitNotifyExample(); executorService.execute(() -> example.after()); executorService.execute(() -> example.before()); } ~~~ ~~~ before after ~~~ ### await() signal() signalAll() java.util.concurrent 類庫中提供了 Condition 類來實現線程之間的協調,可以在 Condition 上調用 await() 方法使線程等待,其它線程調用 signal() 或 signalAll() 方法喚醒等待的線程。相比于 wait() 這種等待方式,await() 可以指定等待的條件,因此更加靈活。 使用 Lock 來獲取一個 Condition 對象。 ~~~java public class AwaitSignalExample { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void before() { lock.lock(); try { System.out.println("before"); condition.signalAll(); } finally { lock.unlock(); } } public void after() { lock.lock(); try { condition.await(); System.out.println("after"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } ~~~ ~~~java public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); AwaitSignalExample example = new AwaitSignalExample(); executorService.execute(() -> example.after()); executorService.execute(() -> example.before()); } ~~~ ~~~ before after ~~~ ### sleep和wait有什么區別 * sleep 和 wait * wait() 是 Object 的方法,而 sleep() 是 Thread 的靜態方法; * wait() 會釋放鎖,sleep() 不會。 * 有什么區別 * sleep() 方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其他線程,但是對象的鎖依然保持,因此休眠時間結束后會自動恢復(線程回到就緒狀態)。 * wait() 是 Object 類的方法,調用對象的 wait() 方法導致當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的 notify() 方法(或 notifyAll() 方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),如果線程重新獲得對象的鎖就可以進入就緒狀態。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看