java並發之TimeUnit理解


TimeUnit是java.util.concurrent包下面的一個類,TimeUnit提供了可讀性更好的線程暫停操作,通常用來替換Thread.sleep(),在很長一段時間里Thread的sleep()方法作為暫停線程的標准方式,幾乎所有Java程序員都熟悉它,事實上sleep方法本身也很常用而且出現在很多面試中。如果你已經使用過Thread.sleep(),當然我確信你這樣做過,那么你一定熟知它是一個靜態方法,暫停線程時它不會釋放鎖,該方法會拋出InterrupttedException異常(如果有線程中斷了當前線程)。但是我們很多人並沒有注意的一個潛在的問題就是它的可讀性。Thread.sleep()是一個重載方法,可以接收長整型毫秒和長整型的納秒參數,這樣對程序員造成的一個問題就是很難知道到底當前線程是睡眠了多少秒、分、小時或者天。看看下面這個Thread.sleep()方法:

Thread.sleep(2400000)

 

 

粗略一看,你能計算出當前線程是等待多長時間嗎?可能有些人可以,但是對於大多數程序員來說這種寫法的可讀性還是很差的,你需要把毫秒轉換成秒和分,讓我們來看看另外一個例子,這個例子比前面那個例子可讀性稍微好一點:

Thread.sleep(4*60*1000);

 

 

這比前面那個例子已經好多了,但是仍然不是最好的,你注意到睡眠時間用毫秒,不容易猜出當前線程將等待4分鍾。TimeUnit類解決了這個問題,通過指定DAYS、HOURS、MINUTES,SECONDS、MILLISECONDS和NANOSECONDS。java.utils.concurrent .TimeUnit 是Java枚舉應用場景中最好的例子之一,所有TimeUnit都是枚舉實例,讓我們來看看線程睡眠4分鍾用TimeUnit是如何使用的。

TimeUnit.MINUTES.sleep(4);  // sleeping for 4 minutes

 

 

類似你可以采用秒、分、小時級別來暫停當前線程。你可以看到這比Thread的sleep方法的可讀的好多了。記住TimeUnit.sleep()內部調用的Thread.sleep()也會拋出InterruptException。你也可以查看JDK源代碼去驗證一下。下面是一個簡單例子,它展示如果使用TimeUnit.sleep()方法。

/**
 *
 * Java program to demonstrate how to use TimeUnit.sleep() method in Java.
 * TimeUnit is a new way of introducing pause in Java program.
 * @author Javin
 */
public class TimeUnitTest {
 
    public static void main(String args[]) throws InterruptedException {
 
        System.out.println("Sleeping for 4 minutes using Thread.sleep()");
        Thread.sleep(4 * 60 * 1000);
        System.out.println("Sleeping for 4 minutes using TimeUnit sleep()");
 
        TimeUnit.SECONDS.sleep(4);
        TimeUnit.MINUTES.sleep(4);
        TimeUnit.HOURS.sleep(1);
        TimeUnit.DAYS.sleep(1);
    }
}

 

 

除了sleep的功能外,TimeUnit還提供了便捷方法用於把時間轉換成不同單位,例如,如果你想把秒轉換成毫秒,你可以使用下面代碼:

TimeUnit.SECONDS.toMillis(44)

 

 

它將返回44,000

TimeUnit vs Thread.sleep()

目前我們討論使用TimeUnit的好處是提高了可讀性,但是有時候覺得其他方法更好,因為Thread.sleep()伴隨java很早就出現了,幾乎所有程序員都知道Thread.sleep(),都知道是將當前線程暫停,而對TimeUnit並不太熟悉。兩個原因:一是對比起Thread.sleep(),TimeUnit不是很常用,第二是在它不在Thread類中,就像wait和notify同樣不是在Thread中,反正這些需要一段時間才能被采用,並成為一個標准的方式。

總結來說在你想用Thread.sleep()方法的地方你最好使用TimeUnit.sleep()方法來代替。它不盡可以提高代碼的可讀性而且能更加熟悉java.util.concurrent包,因為TimeUnit在並發編程中也是一個關鍵API。

-----------------------------------------------------------------------------------

//關於秒的常用方法 
TimeUnit.SECONDS.toMillis(1) 1秒轉換為毫秒數 
TimeUnit.SECONDS.toMinutes(60) 60秒轉換為分鍾數 
TimeUnit.SECONDS.sleep(5) 線程休眠5秒 
TimeUnit.SECONDS.convert(1, TimeUnit.MINUTES) 1分鍾轉換為秒數 

//TimeUnit.DAYS 日的工具類 
//TimeUnit.HOURS 時的工具類 
//TimeUnit.MINUTES 分的工具類 
//TimeUnit.SECONDS 秒的工具類 
//TimeUnit.MILLISECONDS 毫秒的工具類

 

---------------------------------------------------------------------------

 1 import java.util.concurrent.TimeUnit;
 2  
 3 public class TimeUnitDemo {
 4      private TimeUnit timeUnit =TimeUnit.DAYS;
 5  
 6      public static void main(String[] args) {
 7         TimeUnitDemo demo = new TimeUnitDemo();
 8         demo.outInfo();
 9         demo.timeUnit =TimeUnit.HOURS;
10         demo.outInfo();
11         demo.timeUnit =TimeUnit.MINUTES;
12         demo.outInfo();
13         demo.timeUnit =TimeUnit.SECONDS;
14         demo.outInfo();
15     }
16 
17     public void outInfo() {
18         System.out.println(timeUnit.name());
19         System.out.println(timeUnit.toDays(1));
20         System.out.println(timeUnit.toHours(1));
21         System.out.println(timeUnit.toMinutes(1));
22         System.out.println(timeUnit.toMicros(1));
23         System.out.println(timeUnit.toMillis(1));
24         System.out.println(timeUnit.toNanos(1));
25         System.out.println(timeUnit.toSeconds(1));
26         System.out.println("1天有"+(timeUnit.convert(1, TimeUnit.DAYS))+timeUnit.name());
27         System.out.println("12小時"+(timeUnit.convert(12, TimeUnit.HOURS))+timeUnit.name());
28         System.out.println("3600秒有"+(timeUnit.convert(36000, TimeUnit.MINUTES))+timeUnit.name());
29         System.out.println("-------------------");
30     }
31 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM