在设计可由多个线程使用的单例类时,我遇到了以下挑战:
退出主线程和另一个称为客户端的线程。主要方法首先获取一个实例,然后客户端也获取实例。然后客户端执行单例类的方法,我的调试步骤向我显示主线程被中断以执行客户端调用的方法。
如何确保客户端线程执行该方法,而不会中断主线程。
提前感谢您的努力。
干杯 鲍勃
编辑:
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;
}
}
答案 0 :(得分:6)
这与单身人士无关,是吗?您必须使用synchronized
关键字来同步不会中断的方法。这是一个难以回答的问题,有几本书(例如 Doug Lea 'Java并行编程')你可以参考。除此之外,你的问题并没有足够精确地让我添加更多细节。
答案 1 :(得分:2)
然后客户端执行一个方法 单例类我的调试步骤 通过向我展示主线程 被中断以执行该方法 这是由客户调用的。
这是绝对不可能的(除非你的主线程和单例类都包含一些相当复杂的代码来强迫tham这样做,在这种情况下,解决方案当然不是以这种方式实现它们)。很可能你错误地解释了调试器显示的内容。
答案 2 :(得分:0)
可以这样做但你只在“关键部分”,“关键数据”上进行同步。因为,我没有在你的代码中看到任何关键部分,我不认为你真的需要在客户端和主线程之间进行同步。也许这条线可以被视为关键部分:
Event = putDataIntoEvent(message, evaluationMsgStruct, stamp, numOfClient);
但是根据你提供的来源,很难这么说。