EHCache简单使用

说明:本文转自 http://oaklet.iteye.com/blog/309037
按照原文创建一个java project,运行main方法会出现:
java.lang.NoClassDefFoundError: com/test/InsertDate
Caused by: java.lang.ClassNotFoundException: com.test.InsertDate
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Exception in thread "main"
建议创建web 工程,引入strutrs、spring、hibernate相关的包。
 
 
原文正文如下:
关于缓存的话题,在坛子里已经有很多讨论,简单的来说,如果一个应用中80% 的时间内都在访问20% 的数据,那么,这时候就应该使用缓存了。
测试环境:
MySQL 5.0.22,
jdk1.6.0_07,
ehcache-1.6.0-beta2,
mysql-connector-java-3.1.14

测试表:
Sql代码 
  1. CREATE TABLE TEST
  2. (
  3. TEST_ID BIGINT,
  4. TEST_NAME VARCHAR(50),
  5. TEST_TIME TIMESTAMP,
  6. TEST_VALUE DECIMAL(10, 3)
  7. );
CREATE TABLE TEST
(
TEST_ID BIGINT,
TEST_NAME VARCHAR(50),
TEST_TIME TIMESTAMP,
TEST_VALUE DECIMAL(10, 3)
);

支持类:
Java代码 
  1. public class Util {
  2. public static Random rand = new Random();
  3. public static String atoz = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  4. public static String genString(int length) {
  5. StringBuilder re = new StringBuilder(length);
  6. re.append(atoz.charAt(rand.nextInt(52)));
  7. for (int i = 0; i < length; i++) {
  8. re.append(atoz.charAt(rand.nextInt(62)));
  9. }
  10. return re.toString();
  11. }
  12. public static double genDouble() {
  13. double d1 = 5120 * rand.nextDouble();
  14. double d2 = 1024000 * rand.nextDouble();
  15. return d1 + d2;
  16. }
  17. }
public class Util {

    public static Random rand = new Random();
    public static String atoz = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public static String genString(int length) {
        StringBuilder re = new StringBuilder(length);
        re.append(atoz.charAt(rand.nextInt(52)));
        for (int i = 0; i < length; i++) {
            re.append(atoz.charAt(rand.nextInt(62)));
        }
        return re.toString();
    }

    public static double genDouble() {
        double d1 = 5120 * rand.nextDouble();
        double d2 = 1024000 * rand.nextDouble();
        return d1 + d2;
    }
}

插入测试数据:
Java代码 
  1. public static void traditionalInsert(int total) throws Exception {
  2. Thread.sleep(3000);
  3. Timestamp current = new Timestamp(System.currentTimeMillis());
  4. String currentStr = dateFormat.format(current);
  5. System.out.println(currentStr);
  6. Connection conn = DriverManager.getConnection(dbURL, user, pass);
  7. try {
  8. long begin = System.currentTimeMillis();
  9. conn.setAutoCommit(false);
  10. String sql = "INSERT INTO TEST (TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE) VALUES (?, ?, ?, ?)";
  11. PreparedStatement ps = conn.prepareStatement(sql);
  12. for (int i = 1; i <= total; i++) {
  13. ps.setLong(1, i);
  14. ps.setString(2, Util.genString(33));
  15. ps.setTimestamp(3, current);
  16. ps.setBigDecimal(4, new BigDecimal(Util.genDouble()));
  17. ps.addBatch();
  18. if ((i % 500) == 0) {
  19. ps.executeBatch();
  20. }
  21. }
  22. ps.executeBatch();
  23. conn.commit();
  24. long end = System.currentTimeMillis();
  25. System.out.printf("Count:%d Time:%d\n", total, (end - begin));
  26. } catch (Exception ex) {
  27. ex.printStackTrace();
  28. conn.rollback();
  29. } finally {
  30. conn.close();
  31. }
  32. }
public static void traditionalInsert(int total) throws Exception {
        Thread.sleep(3000);
        Timestamp current = new Timestamp(System.currentTimeMillis());
        String currentStr = dateFormat.format(current);
        System.out.println(currentStr);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            conn.setAutoCommit(false);
            String sql = "INSERT INTO TEST (TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE) VALUES (?, ?, ?, ?)";
            PreparedStatement ps = conn.prepareStatement(sql);
            for (int i = 1; i <= total; i++) {
                ps.setLong(1, i);
                ps.setString(2, Util.genString(33));
                ps.setTimestamp(3, current);
                ps.setBigDecimal(4, new BigDecimal(Util.genDouble()));
                ps.addBatch();
                if ((i % 500) == 0) {
                    ps.executeBatch();
                }
            }
            ps.executeBatch();
            conn.commit();
            long end = System.currentTimeMillis();
            System.out.printf("Count:%d Time:%d\n", total, (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
            conn.rollback();
        } finally {
            conn.close();
        }
    }

使用的javaBean:
Java代码 
  1. public class TEST implements Serializable {
  2. private static final long serialVersionUID = 1L;
  3. public Long TEST_ID;
  4. public String TEST_NAME;
  5. public Timestamp TEST_TIME;
  6. public BigDecimal TEST_VALUE;
  7. @Override
  8. public String toString() {
  9. return String.format("ID:%s,,,NAME:%s", TEST_ID, TEST_NAME);
  10. }
  11. }
public class TEST implements Serializable {
	private static final long serialVersionUID = 1L;
	public Long TEST_ID;
	public String TEST_NAME;
	public Timestamp TEST_TIME;
	public BigDecimal TEST_VALUE;
	@Override
	public String toString() {
		return String.format("ID:%s,,,NAME:%s", TEST_ID, TEST_NAME);
	}
}

先试一下缓存到字典中:
Java代码 
  1. public static HashMap<Long, TEST> simpleCache() throws Exception {
  2. HashMap<Long, TEST> cacheid = new HashMap<Long, TEST>();
  3. Class.forName(dbDriver);
  4. Connection conn = DriverManager.getConnection(dbURL, user, pass);
  5. try {
  6. long begin = System.currentTimeMillis();
  7. Statement s = conn.createStatement();
  8. String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";
  9. ResultSet querySet = s.executeQuery(sql);
  10. for (int i = 1; querySet.next(); i++) {
  11. TEST curr = new TEST();
  12. curr.TEST_ID = querySet.getLong(1);
  13. curr.TEST_NAME = querySet.getString(2);
  14. curr.TEST_TIME = querySet.getTimestamp(3);
  15. curr.TEST_VALUE = querySet.getBigDecimal(4);
  16. cacheid.put(curr.TEST_ID, curr);
  17. }
  18. long end = System.currentTimeMillis();
  19. System.out.printf("Time:%d\n", (end - begin));
  20. } catch (Exception ex) {
  21. ex.printStackTrace();
  22. } finally {
  23. conn.close();
  24. }
  25. return cacheid;
  26. }
public static HashMap<Long, TEST> simpleCache() throws Exception {
        HashMap<Long, TEST> cacheid = new HashMap<Long, TEST>();
        Class.forName(dbDriver);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            Statement s = conn.createStatement();
            String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";
            ResultSet querySet = s.executeQuery(sql);
            for (int i = 1; querySet.next(); i++) {
                TEST curr = new TEST();
                curr.TEST_ID = querySet.getLong(1);
                curr.TEST_NAME = querySet.getString(2);
                curr.TEST_TIME = querySet.getTimestamp(3);
                curr.TEST_VALUE = querySet.getBigDecimal(4);
                cacheid.put(curr.TEST_ID, curr);
            }
            long end = System.currentTimeMillis();
            System.out.printf("Time:%d\n", (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            conn.close();
        }
        return cacheid;
    }

缓存到字典中,写法比较简单,使用方便,缺点就是缓存数据量比较少,一般缓存10W就有可能把jvm的缓存给占完了。用ehcache就可以解决缓存数据太少的问题。

一个简单的配置:
Xml代码 
  1. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:noNamespaceSchemaLocation="ehcache.xsd">
  3. <diskStore path="java.io.tmpdir"/>
  4. <defaultCache
  5. maxElementsInMemory="10000"
  6. maxElementsOnDisk="0"
  7. eternal="true"
  8. overflowToDisk="true"
  9. diskPersistent="false"
  10. timeToIdleSeconds="0"
  11. timeToLiveSeconds="0"
  12. diskSpoolBufferSizeMB="50"
  13. diskExpiryThreadIntervalSeconds="120"
  14. memoryStoreEvictionPolicy="LFU"
  15. />
  16. <cache name="demoCache"
  17. maxElementsInMemory="100"
  18. maxElementsOnDisk="0"
  19. eternal="false"
  20. overflowToDisk="false"
  21. diskPersistent="false"
  22. timeToIdleSeconds="119"
  23. timeToLiveSeconds="119"
  24. diskSpoolBufferSizeMB="50"
  25. diskExpiryThreadIntervalSeconds="120"
  26. memoryStoreEvictionPolicy="FIFO"
  27. />
  28. </ehcache>

Cache配置中的几个属性:

name:Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)。
maxElementsInMemory:内存中保持的对象数量。
maxElementsOnDisk:DiskStore中保持的对象数量,默认值为0,表示不限制。
eternal:是否是永恒数据,如果是,则它的超时设置会被忽略。
overflowToDisk:如果内存中数据数量超过maxElementsInMemory限制,是否要缓存到磁盘上。
timeToIdleSeconds:对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。
timeToLiveSeconds:对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。
diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。
diskExpiryThreadIntervalSeconds:对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。
diskSpoolBufferSizeMB:DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。
memoryStoreEvictionPolicy:如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。

获取配置中的demoCache:
Java代码 
  1. CacheManager manager = CacheManager.create("ehcache.xml");
  2. Cache demo = manager.getCache("demoCache");
CacheManager manager = CacheManager.create("ehcache.xml");
Cache demo = manager.getCache("demoCache");

往cache中加入数据:
Java代码 
  1. public static void ehcache() throws Exception {
  2. CacheManager manager = CacheManager.create("ehcache.xml");
  3. manager.addCache("TEST_ID.TEST");
  4. Cache cid = manager.getCache("TEST_ID.TEST");
  5. Class.forName(dbDriver);
  6. Connection conn = DriverManager.getConnection(dbURL, user, pass);
  7. try {
  8. long begin = System.currentTimeMillis();
  9. Statement s = conn.createStatement();
  10. String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";
  11. ResultSet querySet = s.executeQuery(sql);
  12. for (int i = 1; querySet.next(); i++) {
  13. TEST curr = new TEST();
  14. curr.TEST_ID = querySet.getLong(1);
  15. curr.TEST_NAME = querySet.getString(2);
  16. curr.TEST_TIME = querySet.getTimestamp(3);
  17. curr.TEST_VALUE = querySet.getBigDecimal(4);
  18. cid.put(new Element(curr.TEST_ID, curr));
  19. }
  20. long end = System.currentTimeMillis();
  21. System.out.printf("Time:%d\n", (end - begin));
  22. } catch (Exception ex) {
  23. ex.printStackTrace();
  24. } finally {
  25. conn.close();
  26. }
  27. }
public static void ehcache() throws Exception {
        CacheManager manager = CacheManager.create("ehcache.xml");
        manager.addCache("TEST_ID.TEST");
        Cache cid = manager.getCache("TEST_ID.TEST");
        Class.forName(dbDriver);
        Connection conn = DriverManager.getConnection(dbURL, user, pass);
        try {
            long begin = System.currentTimeMillis();
            Statement s = conn.createStatement();
            String sql = "SELECT TEST_ID,TEST_NAME,TEST_TIME,TEST_VALUE FROM TEST";
            ResultSet querySet = s.executeQuery(sql);
            for (int i = 1; querySet.next(); i++) {
                TEST curr = new TEST();
                curr.TEST_ID = querySet.getLong(1);
                curr.TEST_NAME = querySet.getString(2);
                curr.TEST_TIME = querySet.getTimestamp(3);
                curr.TEST_VALUE = querySet.getBigDecimal(4);
                cid.put(new Element(curr.TEST_ID, curr));
            }
            long end = System.currentTimeMillis();
            System.out.printf("Time:%d\n", (end - begin));
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            conn.close();
        }
    }

这里在CacheManager中直接加入了一个叫TEST_ID.TEST的cache。因为只给了一个名字,所以系统会把defaultCache的设置给它clone一份。
使用方法,像字典一样使用就行:
Java代码 
  1. Cache cid = manager.getCache("TEST_ID.TEST");
  2. Element e5120 = cid.get(new Long(5120));
  3. System.out.println(e5120.getValue());
Cache cid = manager.getCache("TEST_ID.TEST");
Element e5120 = cid.get(new Long(5120));
System.out.println(e5120.getValue());


ehcache中数据是以java对象的形式存在的,使用了java的序列化保存到磁盘,所以保存的对象要实现Serializable接口。ehcache还可以支持分布式缓存。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值