不過不一定所有的緩存系統都支持這個配置。經過驗證,Guava Cache是支持的。驗證過程如下:
1、Guava Cache配置,參考:http://blog.csdn.net/clementad/article/details/51250472
2、創建從數據庫獲取數據的類和方法,該方法使用@Cacheable註解:
@Service
public class UserServiceCacheablesImpl implements UserServiceCacheables{
private final static Logger logger = LoggerFactory.getLogger(UserServiceCacheablesImpl.class);
@Autowired
UserDAO userDAO;
@Override
@Cacheable(value="getPhoneNoByUserId")
public String getPhoneNoByUserId(int userId) {
logger.debug("getting data from database, userId={}", userId);
return userDAO.getPhoneNoByUserId(userId);
}
}
3、創建多線程併發的單元測試代碼:
@RunWith(SpringRunner.class)
@SpringBootTest
public class AdminApplicationTests {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
UserServiceCacheables userServiceCacheables;
/**
* 多線程併發測試
*/
@Test
public void multiThreads() throws Exception{
int number = 3; //線程數
ExecutorService executorService = Executors.newFixedThreadPool(number);
List<Future<String>> results = new ArrayList<Future<String>>();
int userId = 26358;
for (int i=0; i < number; i++) { //非阻塞地啓動number個線程,由Future接收結果
Future<String> future = executorService.submit(new MyThread(userId));
//Thread.sleep(300);
results.add(future);
}
for(Future<String> f : results){ //從Future中獲取結果,打印出來
String phoneNo = f.get();
logger.debug(phoneNo);
}
}
class MyThread implements Callable<String>{
int userId;
public MyThread(int userId) {
this.userId = userId;
}
@Override
public String call() throws Exception {
return userServiceCacheables.getPhoneNoByUserId(userId);
}
}
}
4、測試結果:
當設置3個併發線程的時候,會出現3個log:“getting data from database, userId=26358”,說明訪問了3次數據庫。
當修改註解如下之後,只出現一次“getting data from database, userId=26358”,說明只訪問了1次數據庫,另外兩次命中了緩存:
@Cacheable(value="getPhoneNoByUserId", sync=true)