Skip to content

Commit

Permalink
Caches
Browse files Browse the repository at this point in the history
  • Loading branch information
xujijun committed Jun 2, 2015
1 parent f98dd3b commit 403bafd
Show file tree
Hide file tree
Showing 31 changed files with 1,328 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
target/
logs/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
Expand Down
21 changes: 21 additions & 0 deletions .myeclipse/profiler/MyTimer.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="profiler.settings.instrument.empty.methods">true</entry>
<entry key="ProfilerCPUSettings_profile_runnables">true</entry>
<entry key="profiler.settings.n.profiled.threads.limit">32</entry>
<entry key="ProfilerCPUSettings_filter_type">2</entry>
<entry key="profiler.settings.obj.alloc.stack.sampling.depth">-1</entry>
<entry key="profiler.settings.instrument.method.invoke">true</entry>
<entry key="profiler.settings.instr.scheme">1</entry>
<entry key="ProfilerMemorySettings_track_every">10</entry>
<entry key="ProfilerMemorySettings_mode">4</entry>
<entry key="ProfilerCPUSettings_root_classes">com.xjj.**
</entry>
<entry key="ProfilerCPUSettings_filter_value">com.xjj.*</entry>
<entry key="profiler.settings.istrument.getter.setter.methods">true</entry>
<entry key="myeclipse.profiling.mode">0</entry>
<entry key="ProfilerMemorySettings_stacktraces">-1</entry>
<entry key="profiler.settings.sampling.interval">10</entry>
<entry key="profiler.settings.cpu.profiling.type">0</entry>
</properties>
6 changes: 6 additions & 0 deletions .settings/org.eclipse.core.resources.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
eclipse.preferences.version=1
encoding//src/main/resources/db.properties=UTF-8
encoding//src/main/resources/log4j2.xml=UTF-8
encoding//src/main/resources/profile/development.properties=UTF-8
encoding//src/main/resources/profile/production.properties=UTF-8
encoding//src/main/resources/redis.properties=UTF-8
2 changes: 1 addition & 1 deletion .settings/org.eclipse.wst.common.project.facet.core.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="jst.web" version="2.3"/>
<installed facet="maven" version="1.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="java" version="1.7"/>
<installed facet="jst.web" version="3.0"/>
</faceted-project>
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ And some customized utilities, encapsulated open-source code.
另外还有一些小工具、以及对开源代码的二次封装。

Java:
- Cache: A local cache example using spring cache support
- FreeMarker: A simple implementation of freeMarker
- FTP: A simple FTP client with progress shown
- Guava Cache: example for using Guava cache framework
- HTTP
- POI/Excel example
- Redis: A simple example using spring data redis
- Spring Batch
- SpringMVC example
- Timers
Expand Down
64 changes: 59 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
<version>4.12</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
Expand Down Expand Up @@ -46,17 +52,17 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.2.3</version>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.2.3</version>
<version>2.5.3</version>
</dependency>

<dependency>
Expand All @@ -70,6 +76,17 @@
<version>4.1.6.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.2</version>
</dependency>

<!-- FTP -->
<dependency>
<groupId>commons-net</groupId>
Expand Down Expand Up @@ -115,12 +132,49 @@
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>

</dependencies>


<!-- 选择不同的属性为resource中的变量赋值 -->
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>src/main/resources/profile/development.properties</filter>
</filters>
</build>
</profile>
<profile>
<id>production</id>
<build>
<filters>
<filter>src/main/resources/profile/production.properties</filter>
</filters>
</build>
</profile>
</profiles>

<build>
<finalName>MyJavaStudio</finalName>

<!-- 启用filtering功能为resources中的变量赋值 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
73 changes: 73 additions & 0 deletions src/main/java/com/xjj/cache/guava/MyAbstractCallableCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.xjj.cache.guava;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

/**
* 抽象缓存类、缓存模板。
* 子类需要实现fetchOrCalculateData从数据库或其他数据源中获取数据。
*
* @author XuJijun
*
* @param <K>
* @param <V>
* @param <T>
*/
public abstract class MyAbstractCallableCache<K, V, T> {
private int maximumSize = 1000; //最大缓存条数
private int refreshAfterWriteDuration = 10; //刷新数据时间
private TimeUnit timeUnit = TimeUnit.SECONDS; //缺省时间单位(秒)

// 创建缓存
public Cache<K, V> cache;/* = CacheBuilder.newBuilder()
// 缓存数据的条目
.maximumSize(MAXIMUM_SIZE)
// 根据键值对被创建或值被替换后多少时间后移除
.expireAfterWrite(REFRESH_AFTER_WRITE_IN_SECONDS, TimeUnit.SECONDS)
.build();*/

public MyAbstractCallableCache() {
cache = CacheBuilder.newBuilder().maximumSize(maximumSize) //缓存数据的最大条目
.expireAfterWrite(refreshAfterWriteDuration, timeUnit) //记录被创建或值被更新多少时间后被移除
.build();
}

public MyAbstractCallableCache(int maximumSize, int refreshAfterWriteDuration, TimeUnit timeUnit) {
this.maximumSize = maximumSize;
this.refreshAfterWriteDuration = refreshAfterWriteDuration;
this.timeUnit = timeUnit;
cache = CacheBuilder.newBuilder().maximumSize(maximumSize) //缓存数据的最大条目
.expireAfterWrite(refreshAfterWriteDuration, timeUnit) //记录被创建或值被更新多少时间后被移除
.build();
}



public V getCacheData(final K key, final T t){
try {
return cache.get(key, new Callable<V>() {

public V call() throws Exception {
//执行缓存数据方法
return fetchOrCalculateData(key, t);
}
});
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}

/**
* 从数据库或其他数据源中获取数据、或计算数据
* @author XuJijun
* @param key
* @param t 可以被用来进行计算的一个额外参数
* @return
*/
public abstract V fetchOrCalculateData(K key, T t);
}
61 changes: 61 additions & 0 deletions src/main/java/com/xjj/cache/guava/MyAbstractLoadingCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.xjj.cache.guava;

import java.util.concurrent.TimeUnit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;

/**
* 抽象缓存类、缓存模板。
* 子类需要实现fetchData从数据库或其他数据源中获取数据。
* @author Xu
*
* @param <K> key type
* @param <V> value type
*/
public abstract class MyAbstractLoadingCache <K, V> {
//缺省的初始化参数
private static int maximumSize = 100; //最大缓存条数
private static int refreshAfterWriteDuration = 2; //刷新数据时间
private static TimeUnit timeUnit = TimeUnit.SECONDS; //缺省时间单位(秒)

LoadingCache<K, V> cache;

public LoadingCache<K, V> getCache() {
return cache;
}

public MyAbstractLoadingCache() {
this(maximumSize, refreshAfterWriteDuration, timeUnit);
}

public MyAbstractLoadingCache(int maximumSize, int refreshAfterWriteDuration, TimeUnit timeUnit) {
cache = CacheBuilder.newBuilder().maximumSize(maximumSize) //缓存数据的最大条目
//.refreshAfterWrite(refreshAfterWriteDuration, timeUnit) //记录被创建多少时间后被更新
.expireAfterWrite(10, timeUnit) //记录被创建多少时间后被移除
.recordStats()
.removalListener(new RemovalListener<K, V>() {
@Override
public void onRemoval(RemovalNotification<K, V> rn) {
System.out.println(rn.getKey() + "被移除");

}
}).build(new CacheLoader<K, V>() {
@Override
public V load(K key) throws Exception {
return fetchData(key);
}
});
}

/**
* 从数据库或其他数据源中获取一个key-value,并被加载到缓存中。
* @author Xu
* @param key
* @return 连同key一起被加载到缓存中的。
*/
protected abstract V fetchData(K key);
}
37 changes: 37 additions & 0 deletions src/main/java/com/xjj/cache/guava/MyCallableCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.xjj.cache.guava;


/**
* 实现和测试CallableCache
* @author Xu
*
*/
public class MyCallableCache extends MyAbstractCallableCache<String, String, String> {
//饿汉式单例模式
private static final MyCallableCache cc = new MyCallableCache();
private MyCallableCache(){};
public static MyCallableCache getInstance(){
return cc;
}

@Override
public String fetchOrCalculateData(String key, String t) {
System.out.println("fetchOrCalculateData method...");

//返回缓存数据(模拟从数据库获取数据)
return "{key:" + key + ", value:" + key + "'s value, and args: " + t + "}";
}


public static void main(String[] args) {
try {
for (int i = 0; i < 15; i++) {
String value = getInstance().getCacheData("I am key.", "I am arg.");
System.out.println(value);
Thread.sleep(2000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
60 changes: 60 additions & 0 deletions src/main/java/com/xjj/cache/guava/MyLoadingCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.xjj.cache.guava;

import java.util.concurrent.TimeUnit;

/**
* 实现和测试LoadingCache
* @author Xu
*
*/
public class MyLoadingCache extends MyAbstractLoadingCache<String, String> {
private static final int MAXIMUM_SIZE = 1000; //最大缓存条数
private static final int REFRESH_AFTER_WRITE_DURAION = 200; //刷新数据时间
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; //时间单位(秒)

//饿汉式单例模式
private static final MyLoadingCache lc = new MyLoadingCache();
private MyLoadingCache(){
super(MAXIMUM_SIZE, REFRESH_AFTER_WRITE_DURAION, TIME_UNIT);
};

public static MyLoadingCache getInstance(){
return lc;
}

@Override
protected String fetchData(String key) {
System.out.println("fetchData method..."+key);

//返回缓存数据(模拟从数据库获取数据)
return "{key:"+key+", value:"+key+"'s value}";
}

public static void main(String[] args) {
//MyLoadingCache lc = new MyLoadingCache();

try {
for (int i = 0; i < 100; i++) {
String value = lc.getCache().get("I am a key"+i);
System.out.println(value);
}
Thread.sleep(3000);
System.out.println("==========================================");
for (int i = 0; i < 101; i++) {
String value = lc.getCache().get("I am a key"+i);
System.out.println(value);
Thread.sleep(500);
}

for (int i = 101; i >= 0; i--) {
String value = lc.getCache().get("I am a key"+i);
System.out.println(value);
Thread.sleep(200);
}

System.out.println("stats: "+lc.getCache().stats());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Loading

0 comments on commit 403bafd

Please sign in to comment.