[英]Singleton pattern using its methods in different threads
在設計可供多個線程使用的單例類時,我遇到了以下挑戰:
有一個主線程和另一個稱為客戶端的線程。 主要方法首先獲取一個實例,然后客戶端也獲取實例。 然后客戶端執行單例類的方法,我的調試步驟向我顯示主線程被中斷以執行客戶端調用的方法。
如何確保客戶端線程執行該方法,而不會中斷主線程。
提前感謝您的努力。
干杯鮑勃
編輯:
public class SingletonEsperEngine {
private static SingletonEsperEngine esperEngineObject;
//Configuration for the Esper Engine
private static Configuration cepConfig;
//EPSServiceProvider represents the engine instance
private static EPServiceProvider cep;
private static EPRuntime cepRT;
private static EPAdministrator cepAdm;
private static boolean IsAlreadyInitialized;
private static boolean IsNodeIdAvailable;
public static ArrayList<EPStatement> cepStatement;
public static ArrayList<EPStatement> cepLogInfo;
public static ArrayList<EPStatement> cepFilterStatement;
public static HashMap<String, Integer> mStatistics;
public static HashMap<Integer, Integer> mNodeIds;
//Experiment instantions
private static JoinDebug joinDebugExperiment;
private SingletonEsperEngine() {
}
/**
* In order to prevent simultaneous invocation of the getter method
* by 2 threads or more, we add the synchronized keyword to the method
* declaration.
*
* @return SingletonEsperEngine
*/
public static synchronized SingletonEsperEngine getInstance() {
if (esperEngineObject == null) {
esperEngineObject = new SingletonEsperEngine();
IsAlreadyInitialized = false;
IsNodeIdAvailable = false;
}
return esperEngineObject;
}
/**
* InitEsperService
*
* Initialize the Esper Engine to accept MyriaNed messages.
*
* @return
*/
public static synchronized int InitEsperService() {
}
public int dataToEsperEngine(String data, int numOfClient) {
//Split string into timestamp and Myrianed Message 32 bytes
String strTimestampClientSec = data.substring(0, 16);
String strTimestampClientNano = data.substring(16, 32);
String strTimestampSniffer = data.substring(32, 40);
String message = data.substring(40);
String joinBitMask = CONSTANT.JOIN_MESSAGE_bm.substring(2, 4) + CONSTANT.JOIN_MESSAGE_bm.substring(0, 2);
HashMap<String, Object> Event = new HashMap<String, Object>();
//It is an join message
Event = putDataIntoEvent(message, evaluationMsgStruct, stamp, numOfClient);
cepRT.sendEvent(Event, CONSTANT.JOIN_MESSAGE)
if (CONSTANT.DEBUG) {
printEventHashMap(Event, evaluationMsgStruct);
}
return CONSTANT.SUCCESS;
}
當客戶端線程調用dataToEsperEngine()
時會導致此問題
public class Client implements Runnable {
Socket mClientConnectionSocket;
Connection mCon;
//Seperate thread for every client, to handle the communication and event processing
//ClientThread clientThread;
public static Boolean stopClientThreads = false;
public int mMode = CONSTANT.CLIENT_MODE_IDLE;
public int mNumberOfThisClient;
SingletonEsperEngine mEsperSupport;
public Thread t;
private String name;
public void run() {
String tmp = null;
int idleTime = CONSTANT.SHORT_IDLE_TIME;
while (!stopClientThreads) {
try {
tmp = null;
switch (mMode) {
case CONSTANT.CLIENT_MODE_STOP:
//This will cause exiting of the while loop and terminates the thread
stopClientThreads = true;
return;
case CONSTANT.CLIENT_MODE_IDLE:
//Being lazy
break;
case CONSTANT.CLIENT_MODE_RECEIVE_STREAM:
tmp = receiveMessage();
if (tmp != null) {
System.out.println(tmp);
mEsperSupport.dataToEsperEngine(tmp, mNumberOfThisClient);
}
break;
}
//I am aware of the performance issues
//TODO rebuild with execution pool
this.t.sleep(idleTime);
} catch (InterruptedException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
return;
}
Client(Socket cC, String name) {
//Save socket (=connection) into the client class
mClientConnectionSocket = cC;
gui.Debug.logThis("The server made a connection with: " + mClientConnectionSocket.getInetAddress());
mEsperSupport = mEsperSupport.getInstance();
this.name = name;
mMode = CONSTANT.CLIENT_MODE_IDLE;
t = new Thread(this);
t.start();
this.mNumberOfThisClient = Integer.parseInt(name);
//Connect the input and output stream
try {
mCon = new Connection(new BufferedReader(new InputStreamReader(mClientConnectionSocket.getInputStream())), new PrintWriter(mClientConnectionSocket.getOutputStream()));
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String receiveMessage() {
String tmp = null;
try {
tmp = mCon.cFrom.readLine();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
return tmp;
}
}
這與單身人士無關,是嗎? 您必須同步不會被中斷的方法,可能使用synchronized
關鍵字。 這是一個很難回答的問題,有幾本書(比如Doug Lea'Java Concurrent Programming')你可以參考。 除此之外,你的問題沒有足夠精確地說明我添加更多細節。
然后客戶端執行單例類的方法,我的調試步驟通過顯示主線程被中斷來執行客戶端調用的方法。
這是絕對不可能的(除非你的主線程和單例類都包含一些相當復雜的代碼來強迫tham這樣做,在這種情況下,解決方案當然不是以這種方式實現它們)。 很可能你誤解了調試器顯示的內容。
可以這樣做但你只在“關鍵部分”,“關鍵數據”上進行同步。 因為,我沒有在你的代碼中看到任何關鍵部分,我不認為你真的需要在客戶端和主線程之間進行同步。 也許這條線可以被視為關鍵部分:
Event = putDataIntoEvent(message, evaluationMsgStruct, stamp, numOfClient);
但是根據你給出的來源,很難這么說。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.