java基礎(chǔ)-時間相關(guān)(篇一 java7)

簡單介紹一下java時間相關(guān)的操作,以及線程并發(fā)相關(guān)的一些問題

首先,java時間相關(guān)類喊递,常見的情況,分java7和java8兩個版本來討論阳似。

  1. java7相關(guān)的時間操作
@Test
    public void java7DateTest(){

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //日期
        Date myDate = new Date();
        System.out.println(myDate.toString());
        //output Fri Nov 22 09:22:37 CST 2019
        System.out.println(simpleDateFormat.format(myDate));
        //output 2019-11-22 09:23:48

        //字符串轉(zhuǎn)時間戳
        String str = "2019-11-20 11:08:00";
        try{
            Date date = simpleDateFormat.parse(str);
            long ts = date.getTime();
            System.out.println(ts);
        }catch(Exception e){
            e.getMessage();
            System.out.println("here");
        }
        //output 1574219280000


        //時間戳轉(zhuǎn)字符串
        long timestamp = 1574737744449L;
        String timeStr = simpleDateFormat.format(timestamp);
        System.out.println("current Beijing time "+timeStr);
        //output current Beijing time 2019-11-26 11:09:04

        //與時區(qū)相關(guān)
        System.out.println(TimeZone.getDefault());
        //output sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
        System.out.println(System.getProperty("user.timezone"));
        //output Asia/Shanghai

        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        System.out.println("current Chicago time :"+simpleDateFormat.format(timestamp));
        //out put current Chicago time :2019-11-25 21:09:04
    }

代碼這里使用了單元測試的方式來寫的骚勘,不會單元測試的同學(xué),自己加一個main方法來調(diào)用也可以撮奏。
時間相關(guān)的操作俏讹,做的最多就是:時間戳和年月日字符串相互轉(zhuǎn)換
常見的就是,存入數(shù)據(jù)庫的時候存入時間戳畜吊,提取出來給頁面的時候泽疆,需要給年月日字符串。
這里就分化出一些操作玲献,比如殉疼,根據(jù)時區(qū)進行轉(zhuǎn)換梯浪,或者提取單獨的年,月瓢娜,日等挂洛。
整個轉(zhuǎn)換過程中,最核心的類就是 SimpleDateFormat
這個SimpleDateFormat存在一點問題眠砾,就是 線程不安全
首先解釋下 線程不安全
大致意思就是虏劲,在多線程環(huán)境下使用存在一定風(fēng)險
先看下面這個例子

package com.duanmin.redisdemo;

public class ThreadSafeDemo implements Runnable {
    public static int count=1;
    public void run() {
        while(count<10) {
            System.out.println(Thread.currentThread().getName()+"-執(zhí)行前count="+count);
            try {
                count++;
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-執(zhí)行后count="+count);
        }

    }
    public static void main(String[] args) {
        ThreadSafeDemo Thread1=new ThreadSafeDemo();
        Thread mThread1=new Thread(Thread1,"線程1");
        Thread mThread2=new Thread(Thread1,"線程2");
        Thread mThread3=new Thread(Thread1,"線程3");
        mThread1.start();
        mThread2.start();
        mThread3.start();
    }
}

這是一個非常簡單的例子,就是對于i++類型的多線程調(diào)用
執(zhí)行一下褒颈,其中一次的結(jié)果是這樣的

線程1-執(zhí)行前count=1
線程3-執(zhí)行前count=1
線程3-執(zhí)行后count=3
線程2-執(zhí)行前count=1
線程3-執(zhí)行前count=3
線程1-執(zhí)行后count=2
線程1-執(zhí)行前count=5
線程1-執(zhí)行后count=6
線程3-執(zhí)行后count=5
線程2-執(zhí)行后count=4
線程3-執(zhí)行前count=6
線程3-執(zhí)行后count=7
線程1-執(zhí)行前count=6
線程3-執(zhí)行前count=7
線程3-執(zhí)行后count=9
線程3-執(zhí)行前count=9
線程2-執(zhí)行前count=6
線程3-執(zhí)行后count=10
線程1-執(zhí)行后count=8
線程2-執(zhí)行后count=11

執(zhí)行結(jié)果每次都不一樣

然后柒巫,我們只啟動線程1

package com.duanmin.redisdemo;

public class ThreadSafeDemo implements Runnable {
    public static int count=1;
    public void run() {
        while(count<10) {
            System.out.println(Thread.currentThread().getName()+"-執(zhí)行前count="+count);
            try {
                count++;
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-執(zhí)行后count="+count);
        }

    }
    public static void main(String[] args) {
        ThreadSafeDemo Thread1=new ThreadSafeDemo();
        Thread mThread1=new Thread(Thread1,"線程1");
        Thread mThread2=new Thread(Thread1,"線程2");
        Thread mThread3=new Thread(Thread1,"線程3");
        mThread1.start();
       // mThread2.start();
       // mThread3.start();
    }
}

得到的結(jié)果非常穩(wěn)定

線程1-執(zhí)行前count=1
線程1-執(zhí)行后count=2
線程1-執(zhí)行前count=2
線程1-執(zhí)行后count=3
線程1-執(zhí)行前count=3
線程1-執(zhí)行后count=4
線程1-執(zhí)行前count=4
線程1-執(zhí)行后count=5
線程1-執(zhí)行前count=5
線程1-執(zhí)行后count=6
線程1-執(zhí)行前count=6
線程1-執(zhí)行后count=7
線程1-執(zhí)行前count=7
線程1-執(zhí)行后count=8
線程1-執(zhí)行前count=8
線程1-執(zhí)行后count=9
線程1-執(zhí)行前count=9
線程1-執(zhí)行后count=10

多線程執(zhí)行過長中count的值是很亂的,而且最后出現(xiàn)了一個11

整個代碼執(zhí)行的過程哈肖,可以分解一下

1.比較count的值
2.對當(dāng)前count值加1

這兩個步驟吻育,在這段代碼里念秧,是非原子

原子性這個概念淤井,表明一系列操作,一系列執(zhí)行動作摊趾,像原子一樣币狠,不可分割,一系列的操作砾层,要么全執(zhí)行漩绵,要么一個都不執(zhí)行,沒有中間狀態(tài)

放到多線程環(huán)境下肛炮,非原子的多步驟操作止吐,就會出現(xiàn)線程安全的問題

在我們這種常規(guī)的應(yīng)用程序中,在多線程的并發(fā)環(huán)境下侨糟,如果沒有使用額外的同步手段來處理并發(fā)問題碍扔,那么,線程的調(diào)度秕重,是不可控不同,不可預(yù)期的,誰先執(zhí)行溶耘,誰后執(zhí)行二拐,是不確定的

最后出現(xiàn)11的情況可能是這樣的:

1. 線程2拿到count值為9,小于10
   同時線程3也拿到count值9
2. 線程3先執(zhí)行自增凳兵,這時count值為10
3. 線程2執(zhí)行自增百新,這時count值已經(jīng)是10了,加1之后變成11

好了庐扫,線程安全簡單的理解了饭望,對于java7版本的時間類來說澜倦, SimpleDateFormat 存在線程安全問題,從源碼可以看出杰妓。
跟著format往下看源碼藻治,可以找到一段

// Called from Format after creating a FieldDelegate
    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

這里用的 calendar 是這樣定義的:

protected Calendar calendar;

如果在一段代碼中,我們聲明了一個對象:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat()

然后把它放到多線程環(huán)境下使用巷挥,就會出現(xiàn)上面我們demo里面的情況
calendar.setTime(date);
被交叉調(diào)用桩卵,得到的結(jié)果不是自己想要的。

解決辦法有幾種

  1. 在每次使用的地方new一個SimpleDateFormat倍宾,不重復(fù)使用即可
    當(dāng)然雏节,這也會帶來性能的損耗,在一些大型性能高职,每個地方的損耗都會考慮到钩乍。
  2. 在使用的地方加鎖,這個會消耗性能怔锌。
  3. 使用 ThreadLocal寥粹,每個線程用自己的SimpleDateFormat
  4. 使用一些第三方日期類。

java7的時間類埃元,還有一些其他的不方便的地方涝涤。
看下面示例

@Test
    public void getMonthDeom(){
        System.out.println("current time:"+new Date());
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        System.out.println("year number is:"+year);
        int month = calendar.get(Calendar.MONTH);
        System.out.println("month number is:"+month);
        
    }

執(zhí)行完成后,得到的結(jié)果是

current time:Wed Mar 11 14:33:30 CST 2020
year number is:2020
month number is:2

可以看到岛杀,月份阔拳,是少1的,獲取到的月份需要加1才是當(dāng)前月份數(shù)字类嗤。感覺這個是不是程序員的毛病作祟糊肠,啥東西都要從0開始。

總之遗锣,java7的日期類使用起來货裹,需要注意的地方較多,所以黄伊,在java8的時候泪酱,改進了不少。關(guān)于java8的日期類还最,請看下一篇墓阀,java8時間相關(guān)以及final修飾詞

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拓轻,隨后出現(xiàn)的幾起案子斯撮,更是在濱河造成了極大的恐慌,老刑警劉巖扶叉,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勿锅,死亡現(xiàn)場離奇詭異帕膜,居然都是意外死亡,警方通過查閱死者的電腦和手機溢十,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門垮刹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人张弛,你說我怎么就攤上這事荒典。” “怎么了吞鸭?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵寺董,是天一觀的道長。 經(jīng)常有香客問我刻剥,道長遮咖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任造虏,我火速辦了婚禮御吞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酗电。我一直安慰自己魄藕,他們只是感情好内列,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布撵术。 她就那樣靜靜地躺著,像睡著了一般话瞧。 火紅的嫁衣襯著肌膚如雪嫩与。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天交排,我揣著相機與錄音划滋,去河邊找鬼。 笑死埃篓,一個胖子當(dāng)著我的面吹牛处坪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播架专,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼同窘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了部脚?” 一聲冷哼從身側(cè)響起想邦,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎委刘,沒想到半個月后丧没,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹰椒,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年呕童,在試婚紗的時候發(fā)現(xiàn)自己被綠了漆际。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡夺饲,死狀恐怖灿椅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钞支,我是刑警寧澤茫蛹,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站烁挟,受9級特大地震影響婴洼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撼嗓,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一柬采、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧且警,春花似錦粉捻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杏头,卻和暖如春盈包,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背醇王。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工呢燥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寓娩。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓叛氨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棘伴。 傳聞我的和親對象是個殘疾皇子寞埠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1 java同步幾種方法?threadlocal怎么實現(xiàn)排嫌。 java的同步機制 1.synchronized畸裳; 2...
    thxnmw閱讀 456評論 2 0
  • 九種基本數(shù)據(jù)類型的大小,以及他們的封裝類淳地。(1)九種基本數(shù)據(jù)類型和封裝類 (2)自動裝箱和自動拆箱 什么是自動裝箱...
    關(guān)瑋琳linSir閱讀 1,878評論 0 47
  • 想必大家對SimpleDateFormat并不陌生怖糊。SimpleDateFormat 是 Java 中一個非常常用...
    可愛傻妞是我的愛閱讀 1,197評論 0 4
  • 抽象,繼承,封裝,多態(tài) 下面將一一解釋.抽象是將一類對象的共同特征總結(jié)出來構(gòu)造類的過程.包括數(shù)據(jù)抽象和行為抽象兩部...
    高珊珊aim閱讀 956評論 0 0
  • 如果細數(shù)民國時期的才女帅容,林徽因是必不可少的一個,她不但擁有傾城的美貌伍伤,更有出眾的才華并徘,而且關(guān)于她的情感生活,也恍如...
    簡JN閱讀 1,109評論 0 18