前陣子在網上找了個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來取得後進行數據的保存和查找的;
雖然問題算是解決了,但仍是比較迷糊;
但願有懂的大神幫忙指點指點;