構建 高效可伸縮的結果快取

2021-08-30 23:58:59 字數 2158 閱讀 9353

首相建立一下兩個輔助類(介面)

computable介面

public

inte***ce

computable

**expensivefunction **(表示結果的計算過程)

public

class

expensivefunction

implements

computable

}

如果存在則返回結果的值,否則先快取再進行計算。因為hashmap不是執行緒安全的,所以採用了對整個方法進行同步,每次只有乙個方法執行,多執行緒時,乙個執行緒執行,其他都要阻塞,嚴重影響效率,可能還不如不使用快取的程式。

public

class

memoizer1

implements

computable

@override

public

synchronized v compute

(a arg)

throws interruptedexception

return result;

}}

弊端:如果某個執行緒啟動了乙個開銷很大的計算,而其他執行緒不知道,那麼就會重複這個計算。

public

class

memoizer2

implements

computable

@override

public v compute

(a arg)

throws interruptedexception

return result;

}}

解決了上面的問題。futuretask表示乙個計算過程,這個過程可能已經計算完成,也可能正在進行。如果完成有結果,futuretask.get()會立即返回,否則一直阻塞,直到計算結果在返回

**如下:

public

class

memoizer3

implements

computable

@override

public v compute

(a arg)

throws interruptedexception };

futuretask

ft =

newfuturetask

<

>

(eval)

; futuretask = ft;

cache.

put(arg, ft)

; ft.

run();

}try

catch

(executionexception e)

return null;

}}

上述**實現幾乎是完美的,表現良好的併發性(基於concurrenthashmap高效的併發性),但仍然存在兩個執行緒計算相同值的缺陷,但是概率很小。因為compute方法的if{}**塊的非原子的先檢查再執行,所以仍然存在上述可能。根本原因在於復合操作在底層map物件上執行,而這個物件無法通過加鎖來實現原子性,但可以使用concurrentmap中的原子方法putifabsent來避免如下20行所示。

public

class

memoizer

implements

computable

@override

public v compute

(a arg)

throws interruptedexception };

futuretask

ft =

newfuturetask

<

>

(eval)

;//原子操作

futuretask =cache.

putifabsent

(arg, ft);if

(futuretask == null)

}try

catch

(executionexception e)

return null;

}}

java併發 構建高效且可伸縮的結果快取

幾乎所有的伺服器應用都會使用某種形式的快取。重用之前的計算結果能降低延遲,提高吞吐量,但卻要消耗更多記憶體。看上去簡單的快取,可能會將效能瓶頸轉變成伸縮性瓶頸,即使快取是用來提高單執行緒效能的。本文將開發乙個高效且可伸縮的快取,用於改進乙個高計算開銷的計算,我們會從hashmap開始,逐步完善功能,...

構建高效且可伸縮的結果快取引申的併發測試規範化

有些東西其實就是一層紙,當你偶然穿透的時候,就會豁然開朗,眼前一亮。以前總是對一些併發測試不感冒,有時候覺得我從下手的感覺。但是不自己親自測試一把又覺得不放心,於是總是在thread裡面來來回回的修改,在run方法中做這個中修改,總是亂亂的感覺。今天突然從別人的 中頓悟了,體系終於明朗了。我以構建高...

為計算結果建立高效 可伸縮的快取記憶體

復用已有的計算結果可以縮短等待時間,提高吞吐量,代價是占用更多的記憶體。memoizer利用concurrentmap中原子化的putifabsent方法,快取乙個future而不是乙個值,帶來了快取汙染的可能性 如果乙個計算被取消或者,失敗,未來嘗試對這個值進行計算都會表現為取消或者失敗。為了避免...