欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java中的線程讓步y(tǒng)ield()與線程休眠sleep()方法

 更新時間:2016年07月01日 08:59:14   作者:skywangkw  
Java中的線程讓步會讓線程讓出優(yōu)先級,而休眠則會讓線程進入阻塞狀態(tài)等待被喚醒,這里我們對比線程等待的wait()方法,來詳解Java中的線程讓步y(tǒng)ield()與線程休眠sleep()方法

線程讓步: yield()
yield()的作用是讓步。它能讓當前線程由“運行狀態(tài)”進入到“就緒狀態(tài)”,從而讓其它具有相同優(yōu)先級的等待線程獲取執(zhí)行權;但是,并不能保證在當前線程調用yield()之后,其它具有相同優(yōu)先級的線程就一定能獲得執(zhí)行權;也有可能是當前線程又進入到“運行狀態(tài)”繼續(xù)運行!
示例:

class ThreadA extends Thread{
  public ThreadA(String name){ 
    super(name); 
  } 
  public synchronized void run(){ 
    for(int i=0; i <10; i++){ 
      System.out.printf("%s [%d]:%d\n", this.getName(), this.getPriority(), i); 
      // i整除4時,調用yield
      if (i%4 == 0)
        Thread.yield();
    } 
  } 
} 

public class YieldTest{ 
  public static void main(String[] args){ 
    ThreadA t1 = new ThreadA("t1"); 
    ThreadA t2 = new ThreadA("t2"); 
    t1.start(); 
    t2.start();
  } 
} 

(某一次的)運行結果:

t1 [5]:0
t2 [5]:0
t1 [5]:1
t1 [5]:2
t1 [5]:3
t1 [5]:4
t1 [5]:5
t1 [5]:6
t1 [5]:7
t1 [5]:8
t1 [5]:9
t2 [5]:1
t2 [5]:2
t2 [5]:3
t2 [5]:4
t2 [5]:5
t2 [5]:6
t2 [5]:7
t2 [5]:8
t2 [5]:9

結果說明:
“線程t1”在能被4整數的時候,并沒有切換到“線程t2”。這表明,yield()雖然可以讓線程由“運行狀態(tài)”進入到“就緒狀態(tài)”;但是,它不一定會讓其它線程獲取CPU執(zhí)行權(即,其它線程進入到“運行狀態(tài)”),即使這個“其它線程”與當前調用yield()的線程具有相同的優(yōu)先級。

yield() 與 wait()的比較:
我們知道,wait()的作用是讓當前線程由“運行狀態(tài)”進入“等待(阻塞)狀態(tài)”的同時,也會釋放同步鎖。而yield()的作用是讓步,它也會讓當前線程離開“運行狀態(tài)”。它們的區(qū)別是:
(1) wait()是讓線程由“運行狀態(tài)”進入到“等待(阻塞)狀態(tài)”,而不yield()是讓線程由“運行狀態(tài)”進入到“就緒狀態(tài)”。
(2) wait()是會線程釋放它所持有對象的同步鎖,而yield()方法不會釋放鎖。
下面通過示例演示yield()是不會釋放鎖的:

public class YieldLockTest{ 

  private static Object obj = new Object();

  public static void main(String[] args){ 
    ThreadA t1 = new ThreadA("t1"); 
    ThreadA t2 = new ThreadA("t2"); 
    t1.start(); 
    t2.start();
  } 

  static class ThreadA extends Thread{
    public ThreadA(String name){ 
      super(name); 
    } 
    public void run(){ 
      // 獲取obj對象的同步鎖
      synchronized (obj) {
        for(int i=0; i <10; i++){ 
          System.out.printf("%s [%d]:%d\n", this.getName(), this.getPriority(), i); 
          // i整除4時,調用yield
          if (i%4 == 0)
            Thread.yield();
        }
      }
    } 
  } 
} 

(某一次)運行結果:

t1 [5]:0
t1 [5]:1
t1 [5]:2
t1 [5]:3
t1 [5]:4
t1 [5]:5
t1 [5]:6
t1 [5]:7
t1 [5]:8
t1 [5]:9
t2 [5]:0
t2 [5]:1
t2 [5]:2
t2 [5]:3
t2 [5]:4
t2 [5]:5
t2 [5]:6
t2 [5]:7
t2 [5]:8
t2 [5]:9

結果說明:
主線程main中啟動了兩個線程t1和t2。t1和t2在run()會引用同一個對象的同步鎖,即synchronized(obj)。在t1運行過程中,雖然它會調用Thread.yield();但是,t2是不會獲取cpu執(zhí)行權的。因為,t1并沒有釋放“obj所持有的同步鎖”!

線程休眠:sleep()
sleep() 定義在Thread.java中。
sleep() 的作用是讓當前線程休眠,即當前線程會從“運行狀態(tài)”進入到“休眠(阻塞)狀態(tài)”。sleep()會指定休眠時間,線程休眠的時間會大于/等于該休眠時間;在線程重新被喚醒時,它會由“阻塞狀態(tài)”變成“就緒狀態(tài)”,從而等待cpu的調度執(zhí)行。
示例:

class ThreadA extends Thread{
  public ThreadA(String name){ 
    super(name); 
  } 
  public synchronized void run() { 
    try {
      for(int i=0; i <10; i++){ 
        System.out.printf("%s: %d\n", this.getName(), i); 
        // i能被4整除時,休眠100毫秒
        if (i%4 == 0)
          Thread.sleep(100);
      } 
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  } 
} 

public class SleepTest{ 
  public static void main(String[] args){ 
    ThreadA t1 = new ThreadA("t1"); 
    t1.start(); 
  } 
} 

運行結果:

t1: 0
t1: 1
t1: 2
t1: 3
t1: 4
t1: 5
t1: 6
t1: 7
t1: 8
t1: 9

結果說明:
程序比較簡單,在主線程main中啟動線程t1。t1啟動之后,當t1中的計算i能被4整除時,t1會通過Thread.sleep(100)休眠100毫秒。

sleep() 與 wait()的比較:
我們知道,wait()的作用是讓當前線程由“運行狀態(tài)”進入“等待(阻塞)狀態(tài)”的同時,也會釋放同步鎖。而sleep()的作用是也是讓當前線程由“運行狀態(tài)”進入到“休眠(阻塞)狀態(tài)”。
但是,wait()會釋放對象的同步鎖,而sleep()則不會釋放鎖。
下面通過示例演示sleep()是不會釋放鎖的。

public class SleepLockTest{ 

  private static Object obj = new Object();

  public static void main(String[] args){ 
    ThreadA t1 = new ThreadA("t1"); 
    ThreadA t2 = new ThreadA("t2"); 
    t1.start(); 
    t2.start();
  } 

  static class ThreadA extends Thread{
    public ThreadA(String name){ 
      super(name); 
    } 
    public void run(){ 
      // 獲取obj對象的同步鎖
      synchronized (obj) {
        try {
          for(int i=0; i <10; i++){ 
            System.out.printf("%s: %d\n", this.getName(), i); 
            // i能被4整除時,休眠100毫秒
            if (i%4 == 0)
              Thread.sleep(100);
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    } 
  } 
} 

運行結果:

t1: 0
t1: 1
t1: 2
t1: 3
t1: 4
t1: 5
t1: 6
t1: 7
t1: 8
t1: 9
t2: 0
t2: 1
t2: 2
t2: 3
t2: 4
t2: 5
t2: 6
t2: 7
t2: 8
t2: 9

結果說明:
主線程main中啟動了兩個線程t1和t2。t1和t2在run()會引用同一個對象的同步鎖,即synchronized(obj)。在t1運行過程中,雖然它會調用Thread.sleep(100);但是,t2是不會獲取cpu執(zhí)行權的。因為,t1并沒有釋放“obj所持有的同步鎖”!
注意,若我們注釋掉synchronized (obj)后再次執(zhí)行該程序,t1和t2是可以相互切換的。下面是注釋調synchronized(obj) 之后的源碼:

public class SleepLockTest{ 

  private static Object obj = new Object();

  public static void main(String[] args){ 
    ThreadA t1 = new ThreadA("t1"); 
    ThreadA t2 = new ThreadA("t2"); 
    t1.start(); 
    t2.start();
  } 

  static class ThreadA extends Thread{
    public ThreadA(String name){ 
      super(name); 
    } 
    public void run(){ 
      // 獲取obj對象的同步鎖
//      synchronized (obj) {
        try {
          for(int i=0; i <10; i++){ 
            System.out.printf("%s: %d\n", this.getName(), i); 
            // i能被4整除時,休眠100毫秒
            if (i%4 == 0)
              Thread.sleep(100);
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
//      }
    } 
  } 
} 

相關文章

  • Spring?boot2.0?日志集成方法分享(1)

    Spring?boot2.0?日志集成方法分享(1)

    這篇文章主要介紹了Spring?boot2.0?日志集成方法分享,Spring?Boot使用Apache的Commons?Logging作為內部的日志框架,其僅僅是一個日志接口,在實際應用中需要為該接口來指定相應的日志實現,下文日志實現詳情需要的小伙伴可以參考一下
    2022-04-04
  • 詳解SpringBoot構建Docker鏡像的3種方式

    詳解SpringBoot構建Docker鏡像的3種方式

    這篇文章主要介紹了SpringBoot構建Docker鏡像的3種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • java通過ssh連接服務器執(zhí)行shell命令詳解及實例

    java通過ssh連接服務器執(zhí)行shell命令詳解及實例

    這篇文章主要介紹了java通過ssh連接服務器執(zhí)行shell命令詳解及實例方法的相關資料
    2017-02-02
  • 淺談SpringMVC對RESTfull的支持

    淺談SpringMVC對RESTfull的支持

    這篇文章主要介紹了淺談SpringMVC對RESTfull的支持,分享了相關配置代碼,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • 深入理解Java Socket通信

    深入理解Java Socket通信

    本篇文章主要介紹了深入理解Java Socket,Java中的網絡通信是通過Socket實現的,Socket分為ServerSocket和Socket兩大類,有興趣的可以了解一下
    2017-02-02
  • 基于Eclipse中SVN圖標不顯示的解決方法

    基于Eclipse中SVN圖標不顯示的解決方法

    本篇文章是對Eclipse中SVN圖標不顯示的解決方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • Spring Security 表單登錄功能的實現方法

    Spring Security 表單登錄功能的實現方法

    這篇文章主要介紹了Spring Security 表單登錄,本文將構建在之前簡單的 Spring MVC示例 之上,因為這是設置Web應用程序和登錄機制的必不可少的。需要的朋友可以參考下
    2019-06-06
  • idea使用war以及war exploded的區(qū)別說明

    idea使用war以及war exploded的區(qū)別說明

    本文詳細解析了war與warexploded兩種部署方式的差異及步驟,war方式是先打包成war包,再部署到服務器上;warexploded方式是直接把文件夾、class文件等移到Tomcat上部署,支持熱部署,開發(fā)時常用,文章分別列出了warexploded模式和war包形式的具體操作步驟
    2024-10-10
  • hibernate多表操作實例代碼

    hibernate多表操作實例代碼

    這篇文章主要介紹了hibernate多表操作實例代碼,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Seata?環(huán)境搭建部署過程

    Seata?環(huán)境搭建部署過程

    Seata是一個分布式事務,seata服務端也是一個微服務,需要和其他微服務一樣需要注冊中心和配置中心,這篇文章主要介紹了Seata?環(huán)境搭建,需要的朋友可以參考下
    2022-10-10

最新評論