简体   繁体   English

单例模式在不同的线程中使用其方法

[英]Singleton pattern using its methods in different threads

When designing a singleton class which can be used by multiple threads I run into the following challenge: 在设计可供多个线程使用的单例类时,我遇到了以下挑战:

There exits a main thread and another thread called client. 有一个主线程和另一个称为客户端的线程。 The main method first gets an instance and afterwards the clients also get instances. 主要方法首先获取一个实例,然后客户端也获取实例。 And a client then executes a method of the singleton class my debug step through shows me that the main thread is interrupted to execute the method which is called by the client. 然后客户端执行单例类的方法,我的调试步骤向我显示主线程被中断以执行客户端调用的方法。

How can I ensure that the client thread executes the method, without interrupting the main thread. 如何确保客户端线程执行该方法,而不会中断主线程。

Thanks in advance for efforts. 提前感谢您的努力。

Cheers Bob 干杯鲍勃

Edit: 编辑:

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;
    }

The problem is caused when the client thread invokes dataToEsperEngine() 当客户端线程调用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;
    }
}

That has nothing to do with singletons, has it? 这与单身人士无关,是吗? You have to synchronize methods that shall not be interrupted, perhaps using synchronized keyword. 您必须同步不会被中断的方法,可能使用synchronized关键字。 This is a difficult matter to answer in entirety, there are several books (such as Doug Lea 'Concurrent Programming in Java') you may consult. 这是一个很难回答的问题,有几本书(比如Doug Lea'Java Concurrent Programming')你可以参考。 Apart from that, your question is not phrased quite precisely enough for me to add more detail. 除此之外,你的问题没有足够精确地说明我添加更多细节。

And the client then executes a method of the singleton class my debug step through shows me that the main thread is interrupted to execute the method which is called by the client. 然后客户端执行单例类的方法,我的调试步骤通过显示主线程被中断来执行客户端调用的方法。

That's absolutely impossible (unless both your main thread and the singleton class contain some fairly complex code to force tham to do that, in which case the solution is of course not to implement them that way). 这是绝对不可能的(除非你的主线程和单例类都包含一些相当复杂的代码来强迫tham这样做,在这种情况下,解决方案当然不是以这种方式实现它们)。 Most likely you are misinterpreting what the debugger displays. 很可能你误解了调试器显示的内容。

It is possible to do it but you only do synchronization only on "critical sections", "critical data". 可以这样做但你只在“关键部分”,“关键数据”上进行同步。 Since, I did not see any critical section in your code, I dont think you really need a sync between the client and the main thread. 因为,我没有在你的代码中看到任何关键部分,我不认为你真的需要在客户端和主线程之间进行同步。 Maybe this line can be considered as critical section : 也许这条线可以被视为关键部分:

Event = putDataIntoEvent(message, evaluationMsgStruct, stamp, numOfClient);

But with the source you gave, it is difficult to say so. 但是根据你给出的来源,很难这么说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM