文章目录
- guava本地缓存
- 1.引入依赖
- 1.sun-dependencies
- 2.sun-common-redis
- 2.CacheUtil.java封装和使用
-
- 自定义线程工厂+自定义线程池
- 1.自定义线程工厂
- 1.新建一个线程池模块 sun-common-threadpool
- 2.CustomNameThreadFactory.java 自定义线程工厂
- 2.sun-demo模块自定义线程池
- 1.ThreadPoolConfig.java
- 2.引入sun-common-threadpool的依赖
- 3.测试
guava本地缓存
1.引入依赖
1.sun-dependencies
<guava.version>19.0</guava.version>
<fastjson.version>1.2.83</fastjson.version>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
2.sun-common-redis
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
2.CacheUtil.java封装和使用
1.CacheUtil.java
package com.sunxiansheng.redis.util;
import com.alibaba.fastjson.JSON;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@Component
@Slf4j
public class CacheUtil<K, V> {
@Value("${guaca.cache.switch:false}")
private Boolean cacheEnabled;
@Value("${guaca.cache.maximumSize:5000}")
private int maximumSize;
@Value("${guaca.cache.expireAfterAccess:3}")
private int expireAfterAccess;
private static final String CACHE_KEY_SEPARATOR = "_";
private final Cache<String, String> localCache = CacheBuilder.newBuilder()
.maximumSize(maximumSize)
.expireAfterAccess(expireAfterAccess, TimeUnit.SECONDS)
.build();
public Map<K, V> getResult(List<K> skuIdList, String cachePrefix, Class<V> clazz, Function<List<K>, Map<K, V>> function) {
if (CollectionUtils.isEmpty(skuIdList)) {
return Collections.emptyMap();
}
Map<K, V> resultMap = new HashMap<>(16);
if (Boolean.FALSE.equals(cacheEnabled)) {
return function.apply(skuIdList);
}
List<K> noCacheIdList = new LinkedList<>();
for (K skuId : skuIdList) {
String cacheKey = generateCacheKey(cachePrefix, skuId);
String content = localCache.getIfPresent(cacheKey);
if (StringUtils.isNotBlank(content)) {
V v = JSON.parseObject(content, clazz);
resultMap.put(skuId, v);
} else {
noCacheIdList.add(skuId);
}
}
if (!CollectionUtils.isEmpty(noCacheIdList)) {
log.debug("Cache miss for keys: {}", noCacheIdList);
}
if (CollectionUtils.isEmpty(noCacheIdList)) {
return resultMap;
}
Map<K, V> noCacheResultMap = function.apply(noCacheIdList);
if (!CollectionUtils.isEmpty(noCacheResultMap)) {
for (Map.Entry<K, V> entry : noCacheResultMap.entrySet()) {
K skuId = entry.getKey();
V content = entry.getValue();
resultMap.put(skuId, content);
String cacheKey = generateCacheKey(cachePrefix, skuId);
localCache.put(cacheKey, JSON.toJSONString(content));
}
}
return resultMap;
}
public V getSingleResult(K key, String cachePrefix, Class<V> clazz, Function<K, V> function) throws ExecutionException {
String cacheKey = generateCacheKey(cachePrefix, key);
String content = localCache.getIfPresent(cacheKey);
if (StringUtils.isNotBlank(content)) {
return JSON.parseObject(content, clazz);
}
V result = function.apply(key);
if (result != null) {
localCache.put(cacheKey, JSON.toJSONString(result));
}
return result;
}
public void invalidateSingleCache(K key, String cachePrefix) {
String cacheKey = generateCacheKey(cachePrefix, key);
localCache.invalidate(cacheKey);
log.debug("Cache invalidated for key: {}", cacheKey);
}
public void invalidateMultipleCaches(List<K> keys, String cachePrefix) {
List<String> cacheKeys = new ArrayList<>();
for (K key : keys) {
String cacheKey = generateCacheKey(cachePrefix, key);
cacheKeys.add(cacheKey);
log.debug("Cache invalidated for key: {}", cacheKey);
}
localCache.invalidateAll(cacheKeys);
}
public void invalidateAllCaches() {
localCache.invalidateAll();
log.debug("All caches invalidated.");
}
private String generateCacheKey(String prefix, K id) {
return prefix + CACHE_KEY_SEPARATOR + id;
}
}
2.使用方式
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@Service
public class CacheService {
@Autowired
private CacheUtil<String, String> cacheUtil;
public Map<String, String> queryData(List<String> ids) {
return cacheUtil.getResult(ids, "dataPrefix", String.class, this::loadFromDatabase);
}
public String querySingleData(String id) throws ExecutionException {
return cacheUtil.getSingleResult(id, "dataPrefix", String.class, this::loadSingleFromDatabase);
}
public void updateData(String id, String newValue) {
saveToDatabase(id, newValue);
cacheUtil.invalidateSingleCache(id, "dataPrefix");
}
public void updateMultipleData(Map<String, String> dataMap) {
saveMultipleToDatabase(dataMap);
cacheUtil.invalidateMultipleCaches(new ArrayList<>(dataMap.keySet()), "dataPrefix");
}
public void clearAllCaches() {
cacheUtil.invalidateAllCaches();
}
private Map<String, String> loadFromDatabase(List<String> ids) {
return Map.of("id1", "Value for id1", "id2", "Value for id2", "id3", "Value for id3");
}
private String loadSingleFromDatabase(String id) {
return "Value for " + id;
}
private void saveToDatabase(String id, String value) {
System.out.println("Saved " + value + " for " + id + " to database");
}
private void saveMultipleToDatabase(Map<String, String> dataMap) {
dataMap.forEach((id, value) -> System.out.println("Saved " + value + " for " + id + " to database"));
}
}
自定义线程工厂+自定义线程池
1.自定义线程工厂
1.新建一个线程池模块 sun-common-threadpool
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sunxiansheng</groupId>
<artifactId>sun-common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>sun-common-threadpool</artifactId>
<version>${children.version}</version>
</project>
2.CustomNameThreadFactory.java 自定义线程工厂
package com.sunxiansheng.threadpool.config;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class CustomNameThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final ThreadGroup threadGroup;
private final String namePrefix;
public CustomNameThreadFactory(String threadName) {
SecurityManager securityManager = System.getSecurityManager();
threadGroup =
(securityManager != null)
? securityManager.getThreadGroup()
: Thread.currentThread().getThreadGroup();
if (threadName == null || "".equals(threadName.trim())) {
threadName = "pool";
}
namePrefix = threadName
+ "-" + poolNumber.getAndIncrement()
+ "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(threadGroup, r, namePrefix + threadNumber.getAndIncrement());
if (thread.isDaemon()) {
thread.setDaemon(false);
}
if (thread.getPriority() != Thread.NORM_PRIORITY) {
thread.setPriority(Thread.NORM_PRIORITY);
}
return thread;
}
}
2.sun-demo模块自定义线程池
1.ThreadPoolConfig.java
package com.sunxiansheng.user.config;
import com.sunxiansheng.threadpool.config.CustomNameThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration
public class ThreadPoolConfig {
@Bean(name = "myThreadPool")
public ThreadPoolExecutor myThreadPool() {
CustomNameThreadFactory customNameThreadFactory = new CustomNameThreadFactory("myThreadPool");
return new ThreadPoolExecutor(
10,
10,
5,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(),
customNameThreadFactory,
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
2.引入sun-common-threadpool的依赖
<dependency>
<groupId>com.sunxiansheng</groupId>
<artifactId>sun-common-threadpool</artifactId>
<version>${sun-common-version}</version>
</dependency>
3.测试
package com.sunxiansheng.user.config;
import com.sunxiansheng.user.UserApplicaion;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.concurrent.ThreadPoolExecutor;
@SpringBootTest(classes = UserApplicaion.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@Slf4j
class ThreadPoolConfigTest {
@Resource(name = "myThreadPool")
private ThreadPoolExecutor threadPoolExecutor;
@Test
void myThreadPool() {
for (int i = 0; i < 10; i++) {
threadPoolExecutor.submit(() -> {
log.info("当前时间:{}", System.currentTimeMillis());
});
}
}
}