成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你可能不知道但卻很有用的 Java 特性

開發 后端
在這篇文章中你將會學習到一些你可能沒聽過但有用的 Java 特性,這些是我個人常用的一些特性或者是從其他文章中學習到的,重點是關注 API 而不是語言本身。

本文轉載自微信公眾號「 crossoverJie」,作者crossoverJie  。轉載本文請聯系 crossoverJie公眾號。

在這篇文章中你將會學習到一些你可能沒聽過但有用的 Java 特性,這些是我個人常用的一些特性或者是從其他文章中學習到的,重點是關注 API 而不是語言本身。

延遲隊列

眾所周知,在 Java 中有許多類型的集合可以使用,但你聽說過 DelayQueue 嗎?它是一個特定類型的集合,允許我們基于延時時間對數據排序,這是一個非常有意思的類,它實現了 BlockingQueue 接口,只有當數據過期后才能從隊列里取出。

使用它的第一步,你的 class 需要實現 Delayed 接口中的 getDelay 方法,當然也可以不用聲明一個 class,使用 Record 也是可以的。

這是 Java14 的新特性

  1. public record DelayedEvent(long startTime, String msg) implements Delayed { 
  2.  
  3.     public long getDelay(TimeUnit unit) { 
  4.         long diff = startTime - System.currentTimeMillis(); 
  5.         return unit.convert(diff, TimeUnit.MILLISECONDS); 
  6.     } 
  7.  
  8.     public int compareTo(Delayed o) { 
  9.         return (int) (this.startTime - ((DelayedEvent) o).startTime); 
  10.     } 
  11.  

假設我們需要一個延時 10s 取出的數據,我們只需要放入一個比當前時間多 10s 的任務即可。

  1. final DelayQueue<DelayedEvent> delayQueue = new DelayQueue<>(); 
  2. final long timeFirst = System.currentTimeMillis() + 10000; 
  3. delayQueue.offer(new DelayedEvent(timeFirst, "1")); 
  4. log.info("Done"); 
  5. log.info(delayQueue.take().msg()); 

最終輸出如下:

時間格式的日期

這個特性可能對大部分人來說沒什么用,但老實說我個人非常喜歡;不管怎么說 Java 8 在時間 API 上改進了許多。從這個版本開始或許你不再需要其他任何擴展庫了。

你能想到嘛,從 Java 16 中你甚至可以用標準庫表示一天內的日期了,比如 “in the morning” “in the afternoon” ,這是一個新的格式語句 B。

  1. String s = DateTimeFormatter 
  2.   .ofPattern("B"
  3.   .format(LocalDateTime.now()); 
  4. System.out.println(s); 

以下是我的輸出,具體和你當前時間有關。

你可能會想為什么會是調用 “B” 呢,這確實看起來不太直觀,通過下表也許能解答疑惑:

Stamped Lock

在我看來,并發包是 Java 中最有意思的包之一,同時又很少被開發者熟練掌握,特別是長期使用 web 開發框架的開發者。

有多少人曾經使用過 Lock 呢?相對于 synchronized 來說這是一種更靈活的線程同步機制。

從 Java8 開始你可以使用一種新的鎖:StampedLock.StampedLock,能夠替代 ReadWriteLock。

假設現在有兩個線程,一個線程更新金額、一個線程讀取余額;更新余額的線程首先需要讀取金額,再多線程的情況下需要某種同步機制(不然更新數據會發生錯誤),第二個線程用樂觀鎖的方式讀取余額。

  1. StampedLock lock = new StampedLock(); 
  2. Balance b = new Balance(10000); 
  3. Runnable w = () -> { 
  4.    long stamp = lock.writeLock(); 
  5.    b.setAmount(b.getAmount() + 1000); 
  6.    System.out.println("Write: " + b.getAmount()); 
  7.    lock.unlockWrite(stamp); 
  8. }; 
  9. Runnable r = () -> { 
  10.    long stamp = lock.tryOptimisticRead(); 
  11.    if (!lock.validate(stamp)) { 
  12.       stamp = lock.readLock(); 
  13.       try { 
  14.          System.out.println("Read: " + b.getAmount()); 
  15.       } finally { 
  16.          lock.unlockRead(stamp); 
  17.       } 
  18.    } else { 
  19.       System.out.println("Optimistic read fails"); 
  20.    } 
  21. }; 

現在更新和讀取的都用 50 個線程來進行測試,最終的余額將會等于 60000.

  1. ExecutorService executor = Executors.newFixedThreadPool(10); 
  2. for (int i = 0; i < 50; i++) { 
  3.    executor.submit(w); 
  4.    executor.submit(r); 

并發累加器

鎖并并不是并發包中唯一有意思的特性,并發累加器也同樣有趣;它可以根據我們提供的函數更新數據;再多線程更新數據的場景下,LongAccumulator 是比 AtomicLong 更優的選擇。

現在讓我們來看看具體如何使用,我們需要兩個參數進行初始化;第一個是用于累加計算的函數,通常是一個 sum 函數,第二個參數則是累加計算的初始化值。

接下來我們用 10000 作為初始值來創建一個 LongAccumulator,最終結果是多少?其實結果與上文相同,都是 60000,但這次我們并沒有使用鎖。

  1. LongAccumulator balance = new LongAccumulator(Long::sum, 10000L); 
  2. Runnable w = () -> balance.accumulate(1000L); 
  3.  
  4. ExecutorService executor = Executors.newFixedThreadPool(50); 
  5. for (int i = 0; i < 50; i++) { 
  6.    executor.submit(w); 
  7.  
  8. executor.shutdown(); 
  9. if (executor.awaitTermination(1000L, TimeUnit.MILLISECONDS)) 
  10.    System.out.println("Balance: " + balance.get()); 
  11. assert balance.get() == 60000L; 

數組的二分查找

假設我們想在一個排序列表中插入一個新元素,可以使用 Arrays.binarySearch() 函數,當這個 key 存在時將會返回 key 所在的索引,如果不存在時將會返回插入的位置-(insertion point)-1。

binarySearch 是 Java 中非常簡單且有效的查詢方法。

下面的這個例子中,對返回結果取反便能的到索引位置。

  1. int[] t = new int[] {1, 2, 4, 5}; 
  2. int x = Arrays.binarySearch(t, 3); 
  3.  
  4. assert ~x == 2; 

負數的二進制是以正數的補碼表示,對一個數取反+1 就等于補碼,所以這里直接取反就等于 Arrays.binarySearch() 不存在時的返回值了。

Bit Set

如果你需要對二進制數組進行操作你會怎么做?用 boolean[] 布爾數組?

有一種更高效又更省內存的方式,那就是 BitSet。它允許我們存儲和操作 bit 數組,與 boolean[] 相比可省 8 倍的內存;也可以使用 and/or/xor 等邏輯操作。

假設我們現在有兩個 bit 數組,我們需要對他們進行 xor 運算;我們需要創建兩個 BitSet 實例,然后調用 xor 函數。

  1. BitSet bs1 = new BitSet(); 
  2. bs1.set(0); 
  3. bs1.set(2); 
  4. bs1.set(4); 
  5. System.out.println("bs1 : " + bs1); 
  6.  
  7. BitSet bs2 = new BitSet(); 
  8. bs2.set(1); 
  9. bs2.set(2); 
  10. bs2.set(3); 
  11. System.out.println("bs2 : " + bs2); 
  12.  
  13. bs2.xor(bs1); 
  14. System.out.println("xor: " + bs2); 

最終的輸出結果如下:

 

責任編輯:武曉燕 來源: crossoverJie
相關推薦

2012-11-23 10:57:44

Shell

2022-08-13 09:19:07

Bash命令Linux

2020-06-22 08:09:22

GitHub工具開發

2023-01-29 09:46:47

Dialog彈窗模態

2023-02-27 09:20:24

絕對定位CSS

2015-08-13 09:03:14

調試技巧

2020-01-29 19:40:36

Python美好,一直在身邊Line

2021-01-05 11:22:58

Python字符串代碼

2019-11-20 10:25:06

sudoLinux

2021-07-12 07:59:06

安全 HTML 屬性

2019-11-25 14:05:47

Python裝飾器數據

2014-12-08 10:39:15

2019-04-30 08:09:12

Windows 10操作系統工具

2021-12-17 00:10:00

ChromeDevtools功能

2020-03-05 11:10:18

Left join數據庫MySQL

2024-03-04 00:00:00

Kubernetes技巧API

2022-09-20 11:58:27

NpmNode.js

2010-07-29 09:18:31

Linux用戶

2016-09-05 13:14:11

2018-05-10 11:50:13

Docker容器冷知識
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美在线一区二区三区 | 成人免费区一区二区三区 | 99久久免费精品国产免费高清 | 色婷婷综合成人av | 国产精品一区二区久久精品爱微奶 | 国产网站在线播放 | 久久久国产一区二区三区 | 国产中文字幕在线观看 | 一级黄色生活视频 | 天堂资源最新在线 | 精品无码三级在线观看视频 | 欧美在线视频a | 日韩欧美一区在线 | 国产欧美日韩综合精品一 | 亚洲成人免费 | 国产成人福利在线观看 | 亚洲毛片在线观看 | 日韩中文一区二区三区 | h在线看 | 国产精品九九九 | 激情五月综合网 | 人人干人人玩 | 亚洲视频免费在线观看 | www.欧美 | 欧美日韩精品久久久免费观看 | 天堂一区二区三区 | 精品一区二区久久久久久久网站 | 一区二区精品在线 | 色欧美片视频在线观看 | 中文字幕国产一区 | 中文字幕乱码一区二区三区 | 日日干日日 | 亚洲天天| 成年无码av片在线 | 久久免费精品视频 | 激情欧美一区二区三区中文字幕 | 国产精品美女久久久久aⅴ国产馆 | 欧美日韩中文字幕在线 | 久久视频免费看 | 9久久婷婷国产综合精品性色 | 午夜视频大全 |