前阵子在网上找了个demo学了一下memcached的简单使用.java
今天回顾了一下,我想:链接池不是应该算是服务端管理的东西么,Client应该是客户端管理的东西,怎么能放在同一个class里边呢?因而把demo改了改,代码以下:web
服务端:
缓存
package studyMemcached; import com.danga.MemCached.SockIOPool; public class MemServer { private static SockIOPool pool; public static void main(String[] args) { initPool(); } private static void destroyPool() { SockIOPool.getInstance("SP").shutDown(); } private static void initPool() { String[] addr = { "127.0.0.1:11211" }; Integer[] weights = { 3 }; pool = SockIOPool.getInstance("SP"); pool.setServers(addr); pool.setWeights(weights); pool.setInitConn(4); pool.setMinConn(4); pool.setMaintSleep(30); pool.setMaxConn(200); pool.setMaxIdle(1000 * 30 * 30 * 6); pool.setMaintSleep(30); pool.setNagle(false); pool.setSocketTO(30); pool.setSocketConnectTO(0); pool.initialize(); } }
客户端:memcached
package studyMemcached; import java.util.Date; import com.danga.MemCached.MemCachedClient; public class PutToCache { public static void main(String[] args) { MemCachedClient client = new MemCachedClient("SP" ); client.setCompressEnable(true); client.setCompressThreshold(1000 * 1024); // 将数据放入缓存 client.set("test2", "test2"); // 将数据放入缓存,并设置失效时间 Date date = new Date(2000000); client.set("test1", "test1", date); client.add("kkk", "kkkkk"); // 删除缓存数据 // client.delete("test1"); // 获取缓存数据 String str = (String) client.get("test1"); String str2 = (String) client.get("test2"); System.out.println(str); System.out.println(str2); System.out.println((String)client.get("kkk")); } }
先运行服务端,发现立刻程序就结束了;感受有点儿不对劲;线程
而后运行客户端,果真什么也没存进去,什么也没取到;日志
日志里出现这样的提示:Attempting to get SockIO from uninitialized pool!code
想了想,多是链接池初始化之后又立刻被销毁了;server
因而把服务端改为以下这样:对象
package studyMemcached; import java.util.Scanner; import com.danga.MemCached.SockIOPool; public class MemServer { private static SockIOPool pool; public static void main(String[] args) { Scanner sc = new Scanner(System.in); initPool(); while(!sc.nextLine().equals("exit")) { } sc.close(); destroyPool(); } private static void destroyPool() { SockIOPool.getInstance("SP").shutDown(); } private static void initPool() { String[] addr = { "127.0.0.1:11211" }; Integer[] weights = { 3 }; pool = SockIOPool.getInstance("SP"); pool.setServers(addr); pool.setWeights(weights); pool.setInitConn(4); pool.setMinConn(4); pool.setMaintSleep(30); pool.setMaxConn(200); pool.setMaxIdle(1000 * 30 * 30 * 6); pool.setMaintSleep(30); pool.setNagle(false); pool.setSocketTO(30); pool.setSocketConnectTO(0); pool.initialize(); } }
让服务端卡在那里等待输入,而后运行客户端,这样会不会就能够从链接池获取到链接了呢?blog
...
...
果真仍是不行;
依然提示:Attempting to get SockIO from uninitialized pool!
难道这两部分代码必定要放在同一个类文件中么?这是什么鬼逻辑;
回头查看公司项目里memcached部分的代码,也是把链接池和建立Client实例的逻辑分开在两个类文件里的,没有任何问题;
想来想去,作了个伪分开,把Client做为服务端的一个静态变量,和线程池一块儿初始化,而后在另外一个类里调用这个Client进行存取,这个天然是能够的;
后来又想到,公司的项目是web项目,是部署在web容器里的,会不会由于Client和线程池对象都在同一个classloader或context里,因此才能够互相找到呢?
可是这个无法验证啊,还得写一个web版的demo,太费劲了,,,
因而,写了这样同样东西:Together类,有两个field,一个Client,一个Server分别是持有缓存Client和链接池对象的独立的类;在初始化Together对象的时候,分别将client和Pool在各自的构造方法中初始化,而后在Together对象中调用Client里的缓存Client进行存取;
代码以下:
Together:
package studyMemcached; public class Together { private MemC client; private MemS server; public Together() { client = new MemC(); server = new MemS(); } public static void main(String[] args) { String mistery = "xxx"; Together t = new Together(); t.client.set("mis", mistery); System.out.println(t.client.get("mis")); } }
Server端:
package studyMemcached; import com.danga.MemCached.SockIOPool; public class MemS { private SockIOPool pool; public MemS() { String[] addr = { "127.0.0.1:11211" }; Integer[] weights = { 3 }; pool = SockIOPool.getInstance("SP"); pool.setServers(addr); pool.setWeights(weights); pool.setInitConn(4); pool.setMinConn(4); pool.setMaintSleep(30); pool.setMaxConn(200); pool.setMaxIdle(1000 * 30 * 30 * 6); pool.setMaintSleep(30); pool.setNagle(false); pool.setSocketTO(30); pool.setSocketConnectTO(0); pool.initialize(); } }
Client端:
package studyMemcached; import java.util.Date; import com.danga.MemCached.MemCachedClient; public class MemC { public MemCachedClient client; public MemC() { client = new MemCachedClient("SP"); client.setCompressEnable(true); client.setCompressThreshold(64 * 1024); } public void set(String key, String value) { client.set(key, value, new Date(2000000)); } public String get(String key) { return (String) client.get(key); } }
这样一来,MemCachedClient和SockIOPool就分开了,只是在实例化的时候两个实例处在同一个classloader里;
这样调用,发现能够进行数据的存取了;
看来互相找不到是一种相似不在同一个会话环境的问题;
我在网上百度了一天,也没发现有人吧Client和Pool的初始化分开写的demo,能找到的demo总共就俩,都是写在一块儿的;
可能这个pool不算是服务端吧,或者Client不算是客户端;
公司的项目里是把Client做为一个单例,用的时候getInstance来取得后进行数据的保存和查找的;
虽然问题算是解决了,但仍是比较迷糊;
但愿有懂的大神帮忙指点指点;