Синглтон-паттерн с использованием его методов в разных потоках - PullRequest
4 голосов
/ 18 апреля 2011

При разработке одноэлементного класса, который может использоваться несколькими потоками, я сталкиваюсь со следующей проблемой:

Выход из основного потока и другого потока, называемого клиентом. Метод main сначала получает экземпляр, а затем клиенты также получают экземпляры. И затем клиент выполняет метод синглтон-класса, через который проходит мой этап отладки, и показывает, что основной поток прерывается для выполнения метода, который вызывается клиентом.

Как я могу убедиться, что клиентский поток выполняет метод, не прерывая основной поток.

Заранее спасибо за усилия.

Приветствие Боб

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

Проблема возникает, когда поток клиента вызывает 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;
    }
}

Ответы [ 3 ]

6 голосов
/ 18 апреля 2011

Это не имеет ничего общего с одиночками, не так ли?Вы должны синхронизировать методы, которые не должны прерываться, возможно, используя ключевое слово synchronized.На этот вопрос сложно ответить полностью, есть несколько книг (например, Даг Ли «Параллельное программирование в Java»), с которыми вы можете обратиться.Кроме того, ваш вопрос сформулирован недостаточно точно, чтобы я мог добавить больше деталей.

2 голосов
/ 18 апреля 2011

И тогда клиент выполняет метод синглтон-класса. Мой этап отладки показывает, что основной поток прерывается для выполнения метода, который вызывается клиентом.

ЭтоАбсолютно невозможно (если только ваш основной поток и класс синглтона не содержат довольно сложный код, чтобы заставить их сделать это, и в этом случае решение, конечно, состоит в том, чтобы не реализовывать их таким образом).Скорее всего, вы неверно истолковываете то, что отображает отладчик.

0 голосов
/ 18 апреля 2011

Это возможно сделать, но вы делаете синхронизацию только на «критических разделах», «критических данных».Поскольку я не видел ни одного критического раздела в вашем коде, я не думаю, что вам действительно нужна синхронизация между клиентом и основным потоком.Возможно, эту строку можно рассматривать как критическую секцию:

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

Но с указанным вами источником трудно сказать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...