自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

本文轉(zhuǎn)載自微信公眾號「 crossoverJie」,作者crossoverJie  。轉(zhuǎn)載本文請聯(lián)系 crossoverJie公眾號。

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

延遲隊列

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

使用它的第一步,你的 class 需要實現(xiàn) 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.  

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

  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 中你甚至可以用標準庫表示一天內(nèi)的日期了,比如 “in the morning” “in the afternoon” ,這是一個新的格式語句 B。

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

以下是我的輸出,具體和你當前時間有關(guān)。

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

Stamped Lock

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

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

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

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

  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. }; 

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

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

并發(fā)累加器

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

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

接下來我們用 10000 作為初始值來創(chuàng)建一個 LongAccumulator,最終結(jié)果是多少?其實結(jié)果與上文相同,都是 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; 

數(shù)組的二分查找

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

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

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

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

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

Bit Set

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

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

假設(shè)我們現(xiàn)在有兩個 bit 數(shù)組,我們需要對他們進行 xor 運算;我們需要創(chuàng)建兩個 BitSet 實例,然后調(diào)用 xor 函數(shù)。

  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); 

最終的輸出結(jié)果如下:

 

責(zé)任編輯:武曉燕 來源: crossoverJie
相關(guān)推薦

2022-08-13 09:19:07

Bash命令Linux

2012-11-23 10:57:44

Shell

2020-06-22 08:09:22

GitHub工具開發(fā)

2015-08-13 09:03:14

調(diào)試技巧

2019-11-20 10:25:06

sudoLinux

2020-01-29 19:40:36

Python美好,一直在身邊Line

2021-01-05 11:22:58

Python字符串代碼

2023-01-29 09:46:47

Dialog彈窗模態(tài)

2023-02-27 09:20:24

絕對定位CSS

2014-12-08 10:39:15

2019-11-25 14:05:47

Python裝飾器數(shù)據(jù)

2021-07-12 07:59:06

安全 HTML 屬性

2019-04-30 08:09:12

Windows 10操作系統(tǒng)工具

2021-12-17 00:10:00

ChromeDevtools功能

2018-05-10 11:50:13

Docker容器冷知識

2020-03-05 11:10:18

Left join數(shù)據(jù)庫MySQL

2010-07-29 09:18:31

Linux用戶

2022-09-20 11:58:27

NpmNode.js

2016-09-05 13:14:11

2024-03-04 00:00:00

Kubernetes技巧API
點贊
收藏

51CTO技術(shù)棧公眾號