国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java8新特性之線程安全日期類

Java8新特性之線程安全日期類

2021-09-08 10:55wzq_55552 Java教程

這篇文章主要介紹了Java8新特性之線程安全日期類,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有一定的幫助,需要的朋友可以參考下

localdatetime

java8新特性之一,新增日期類。

在項目開發過程中經常遇到時間處理,但是你真的用對了嗎,理解阿里巴巴開發手冊中禁用static修飾simpledateformat嗎

通過閱讀本篇文章你將了解到:

  • 為什么需要localdate、localtime、localdatetime【java8新提供的類】
  • java8新的時間api的使用方式,包括創建、格式化、解析、計算、修改

可以使用instant代替 date,localdatetime代替 calendar,datetimeformatter 代替 simpledateformat。

simpledateformat線程不安全

date如果不格式化,打印出的日期可讀性差

?
1
tue sep 10 09:34:04 cst 2019

使用simpledateformat對時間進行格式化,但simpledateformat是線程不安全的 simpledateformat的format方法最終調用源碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private stringbuffer format(date date, stringbuffer toappendto,
                              fielddelegate delegate) {
        // convert input date to time field list
        calendar.settime(date);
 
        boolean usedateformatsymbols = usedateformatsymbols();
 
        for (int i = 0; i < compiledpattern.length; ) {
            int tag = compiledpattern[i] >>> 8;
            int count = compiledpattern[i++] & 0xff;
            if (count == 255) {
                count = compiledpattern[i++] << 16;
                count |= compiledpattern[i++];
            }
 
            switch (tag) {
            case tag_quote_ascii_char:
                toappendto.append((char)count);
                break;
 
            case tag_quote_chars:
                toappendto.append(compiledpattern, i, count);
                i += count;
                break;
 
            default:
                subformat(tag, count, delegate, toappendto, usedateformatsymbols);
                break;
            }
        }
        return toappendto;
    }

注意calendar.settime(date);,calendar類是里面基本都是final修飾的,calendar是共享變量,并且這個共享變量沒有做線程安全控制。當多個線程同時使用相同的simpledateformat對象【如用static修飾的simpledateformat,一般會封裝在工具類,復用】調用format方法時,多個線程會同時調用calendar.settime方法,可能一個線程剛設置好time值另外的一個線程馬上把設置的time值給修改了導致返回的格式化時間可能是錯誤的。

在多并發情況下使用simpledateformat需格外注意:

simpledateformat除了format方法是線程不安全以外,parse方法也是線程不安全的。parse方法實際調用alb.establish(calendar).gettime()方法來解析,alb.establish(calendar)方法里主要完成了

  • 重置日期對象cal的屬性值
  • 使用calb(calbuilder)中屬性設置cal
  • 返回設置好的cal對象

但是這三步不是原子操作

simpledateformat如何保證線程安全

  • 避免線程之間共享一個simpledateformat對象,每個線程使用時都創建一次simpledateformat對象 => 創建和銷毀對象的開銷大
  • 對使用format和parse方法的地方進行加鎖 => 線程阻塞性能差
  • 使用threadlocal保證每個線程最多只創建一次simpledateformat對象 => 較好的方法

date對時間處理比較麻煩,比如想獲取某年、某月、某星期,以及n天以后的時間,如果用date來處理的話真是太難了,你可能會說date類不是有getyear、getmonth這些方法嗎,獲取年月日很easy,但都被棄用了啊

java8全新的日期和時間api

在使用java程序操作數據庫時,我們需要把數據庫類型與java類型映射起來。下表是數據庫類型與java新舊api的映射關系:

數據庫 對應java類(舊) 對應java類(新)
datetime java.util.date localdatetime
date   java.sql.date localdate
time  java.sql.time  localtime
timestamp  java.sql.timestamp  localdatetime

 localdate

只會獲取年月日

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//獲取當前年月日
        localdate localdate = localdate.now();
        //構造指定的年月日
        localdate localdate1 = localdate.of(2019, 9, 10);
 
        //獲取年、月、日、星期幾
        int year = localdate.getyear();
        int year1 = localdate.get(chronofield.year);
        month month = localdate.getmonth();
        int month1 = localdate.get(chronofield.month_of_year);
        int day = localdate.getdayofmonth();
        int day1 = localdate.get(chronofield.day_of_month);
        dayofweek dayofweek = localdate.getdayofweek();
        int dayofweek1 = localdate.get(chronofield.day_of_week);

localtime

只會獲取幾點幾分幾秒

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//創建localtime
        localtime localtime = localtime.of(13, 51, 10);
        localtime localtime1 = localtime.now();
 
        //獲取小時
        int hour = localtime.gethour();
        int hour1 = localtime.get(chronofield.hour_of_day);
        //獲取分
        int minute = localtime.getminute();
        int minute1 = localtime.get(chronofield.minute_of_hour);
        //獲取秒
        int second = localtime.getsecond();
        int second1 = localtime.get(chronofield.second_of_minute);

localdatetime

獲取年月日時分秒,等于localdate+localtime

?
1
2
3
4
5
6
7
8
9
10
11
12
//創建對象
        localdatetime localdatetime = localdatetime.now();
        localdatetime localdatetime1 = localdatetime.of(2019, month.september, 10, 14, 46, 56);
        //localdate+localtime-->localdatetime
        localdatetime localdatetime2 = localdatetime.of(localdate, localtime);
        localdatetime localdatetime3 = localdate.attime(localtime);
        localdatetime localdatetime4 = localtime.atdate(localdate);
 
        //獲取localdate
        localdate localdate2 = localdatetime.tolocaldate();
        //獲取localtime
        localtime localtime2 = localdatetime.tolocaltime();

zoneddatetime

localdatetime總是表示本地日期和時間,要表示一個帶時區的日期和時間,我們就需要zoneddatetime

可以簡單地把zoneddatetime理解成localdatetimezoneidzoneidjava.time引入的新的時區類,注意和舊的java.util.timezone區別。

創建一個zoneddatetime對象

?
1
2
3
4
// 默認時區
zoneddatetime zbj = zoneddatetime.now();
// 用指定時區獲取當前時間
zoneddatetime zny = zoneddatetime.now(zoneid.of("america/new_york"));

結果:

2019-09-15t20:58:18.786182+08:00[asia/shanghai]
2019-09-15t08:58:18.788860-04:00[america/new_york]

另一種創建方式是通過給一個localdatetime附加一個zoneid,就可以變成zoneddatetime

?
1
2
3
localdatetime ldt = localdatetime.of(2019, 9, 15, 15, 16, 17);
zoneddatetime zbj = ldt.atzone(zoneid.systemdefault());
zoneddatetime zny = ldt.atzone(zoneid.of("america/new_york"));

時區轉換

要轉換時區,首先我們需要有一個zoneddatetime對象,然后,通過withzonesameinstant()將關聯時區轉換到另一個時區,轉換后日期和時間都會相應調整。

?
1
2
3
zoneddatetime zbj = zoneddatetime.now(zoneid.of("asia/shanghai"));
// 轉換為紐約時間:
zoneddatetime zny = zbj.withzonesameinstant(zoneid.of("america/new_york"));

zoneddatetime仍然提供了plusdays()等加減操作。

要特別注意,時區轉換的時候,由于夏令時的存在,不同的日期轉換的結果很可能是不同的。這是北京時間9月15日的轉換結果:

2019-09-15t21:05:50.187697+08:00[asia/shanghai]
2019-09-15t09:05:50.187697-04:00[america/new_york]

這是北京時間11月15日的轉換結果:

2019-11-15t21:05:50.187697+08:00[asia/shanghai]
2019-11-15t08:05:50.187697-05:00[america/new_york]

兩次轉換后的紐約時間有1小時的夏令時時差。涉及到時區時,千萬不要自己計算時差,否則難以正確處理夏令時。有了zoneddatetime,將其轉換為本地時間就非常簡單:

?
1
2
zoneddatetime zdt = ...
localdatetime ldt = zdt.tolocaldatetime();

轉換為localdatetime時,直接丟棄了時區信息。

instant

獲取秒數或時間戳

?
1
2
3
4
5
6
7
//創建instant對象
        instant instant = instant.now();
        //獲取秒數
        long currentsecond = instant.getepochsecond();
        //獲取毫秒數
        long currentmilli = instant.toepochmilli();
        long l = system.currenttimemillis();

system.currenttimemillis()也可以獲取毫秒數。

日期計算

localdate、localtime、localdatetime、instant為不可變對象,修改這些對象對象會返回一個副本

增加、減少年數、月數、天數等,以localdatetime為例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//修改localdate、localtime、localdatetime、instant
        localdatetime localdatetime = localdatetime.of(2019, month.september, 10,
                14, 46, 56);
        //增加一年
        localdatetime = localdatetime.plusyears(1);
        localdatetime = localdatetime.plus(1, chronounit.years);
        //減少一個月
        localdatetime = localdatetime.minusmonths(1);
        localdatetime = localdatetime.minus(1, chronounit.months);
 
        //通過with修改某些值
        //修改年為2020
        localdatetime = localdatetime.withyear(2020);
        //修改為2022
        localdatetime = localdatetime.with(chronofield.year, 2022);
        //還可以修改月、日

有些時候想知道這個月的最后一天是幾號、下個周末是幾號,通過提供的時間和日期api可以很快得到答案

?
1
2
localdate localdate = localdate.now();
localdate localdate1 = localdate.with(temporaladjusters.firstdayofyear());

比如通過firstdayofyear()返回了當前年的第一天日期,還有很多方法這里不在舉例說明

格式化時間

datetimeformatter默認提供了多種格式化方式,如果默認提供的不能滿足要求,可以通過datetimeformatter的ofpattern方法創建自定義格式化方式

?
1
2
3
4
5
6
localdate localdate = localdate.of(2019, 9, 10);
string s1 = localdate.format(datetimeformatter.basic_iso_date);
string s2 = localdate.format(datetimeformatter.iso_local_date);
//自定義格式化
datetimeformatter datetimeformatter = datetimeformatter.ofpattern("dd/mm/yyyy");
string s3 = localdate.format(datetimeformatter);

解析時間

和simpledateformat相比,datetimeformatter是線程安全的

?
1
2
localdate localdate1 = localdate.parse("20190910", datetimeformatter.basic_iso_date);
localdate localdate2 = localdate.parse("2019-09-10", datetimeformatter.iso_local_date);

datetimeformatter替代simpledateformat

使用舊的date對象時,我們用simpledateformat進行格式化顯示。使用新的localdatetimezonedlocaldatetime時,我們要進行格式化顯示,就要使用datetimeformatter

simpledateformat不同的是,datetimeformatter不但是不變對象,它還是線程安全的。因為simpledateformat不是線程安全的,使用的時候,只能在方法內部創建新的局部變量。而datetimeformatter可以只創建一個實例,到處引用。

?
1
2
3
4
5
6
//構造器1:傳入格式字符串
datetimeformatter formatter = datetimeformatter.ofpattern("yyyy-mm-dd hh:mm:ss");
 
//構造器2:傳入格式字符串和地區
datetimeformatter formatter = datetimeformatter.ofpattern("e, yyyy-mmmm-dd hh:mm:ss", locale.us);
datetimeformatter formatter = datetimeformatter.ofpattern("e, yyyy-mmmm-dd hh:mm:ss", locale.china);

datetimeformatter底層原理

datetimeformatter線程安全的?為什么?

源碼:

Java8新特性之線程安全日期類

很明顯,通過final修飾類,不可被繼承,final修飾變量,做成了不可變類,類似string,不僅線程安全而且高效。全局可以只有一個對象,多個線程引用。

format和parse線程安全替代

使用localdatetime的format和parse方法,傳入對應的datetimeformatter對象參數,實際也是調用datetimeformatter的format和parse方法,實現日期格式化和解析,是線程安全的。

datetimeformatter類解析localdatetime中的日期變量,轉成stringbuilder返回。localdatetime等新出的日期類全是final修飾的類,不能被繼承,且對應的日期變量都是final修飾的,也就是不可變類。賦值一次后就不可變,不存在多線程數據問題。

Java8新特性之線程安全日期類

到此這篇關于java8新特性之線程安全日期類的文章就介紹到這了,更多相關java8線程安全日期類內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/qq_43409401/article/details/115696152

延伸 · 閱讀

精彩推薦
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7472021-02-04
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 国产精品毛片在线 | 精品国产青草久久久久福利 | 国产高清无密码一区二区三区 | av网站入口 | 亚洲黄色特级片 | 999精品视频 | 人人玩人人添人人澡97 | 中文字幕第一页在线 | 国产高清在线精品一区二区三区 | 天堂一区二区三区 | chengrenzaixian | 毛片免费观看 | 在线国产一级片 | 亚洲国产成人av | 精品无人乱码一区二区三区 | 日韩久色 | 亚洲精品在线视频 | 亚洲国产精品一区二区第一页 | 亚洲 综合 清纯 丝袜 自拍 | 色香阁99久久精品久久久 | 人人人人澡人人爽人人澡 | 在线中文视频 | 91在线看黄 | 精品久久久久久久久久 | 不卡一区| 免费精品人在线二线三线区别 | 久久久综合网 | 九色在线观看 | 在线观看国产精品一区 | 四虎影视免费看电影 | 成人精品一区二区 | 精品国产一区二区三区久久 | 亚洲精品日本 | 免费黄网站在线观看 | 国内在线精品 | 亚洲中午字幕 | 日日干夜夜操 | 在线免费观看黄 | 四季久久免费一区二区三区四区 | 欧美亚洲一 | 成人激情在线视频 |