Как ждать поток, пока не будет создан объект? - PullRequest
0 голосов
/ 07 апреля 2019

В моем приложении для Android мне нужно отправить данные между двумя приложениями.Когда GameClient инициализируется, он запускает три потока.Первый создаст Socket и ReceivingThread.Мне нужно сделать это в потоке, потому что Android не позволяет мне подключиться к сети через MainThread:

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            if (mSocket == null) {
                setSocket(new Socket(mAddress, mPort));
                Log.d(TAG, "Client-Socket set.");
            } else {
                Log.d(TAG, "Socket already set. Skip.");
            }
            mRecCardThread = new ReceivingCardThread();
            mRecCardThread.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();
mSendCardThread = new SendingCardThread();
mSendCardThread.start();

После этого я создаю третий поток для отправки данных.

Проблемапроисходит, когда я подключаюсь к другому телефону и сразу хочу отправить некоторые данные.

mConnection.connectToServer(d.getHost(), d.getPort());
mConnection.sendCard(new int[]{0, 0, 0});

Мой отправляющий поток пытается отправить данные, но часто будет вызываться раньше, чем метод setSocket.

private synchronized void setSocket(Socket socket) {
    Log.d(TAG, "setSocket called");
    if (mSocket != null) {
        if (mSocket.isConnected()) {
            try {
                mSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    mSocket = socket;
    if (mClient != null)
        mClient.mSendCardThread.notifyAll();
    Log.d(TAG, "Notify all, that Socket is set");
}

private class SendingCardThread extends Thread {
    BlockingQueue<int[]> mCardQueue = new ArrayBlockingQueue<>(10);
    private ObjectOutputStream mOutput;

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                int[] nums = mCardQueue.take();
                sendCard(nums);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized void sendCard(int[] nums) {
        try {
            if (mOutput == null) {
                while (mSocket == null) {
                    Log.d(TAG, "Waiting for Socket to be set.");
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, "Not waiting anymore.");
                }
                mOutput = new ObjectOutputStream(mSocket.getOutputStream());
            }
            mOutput.writeObject(nums);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "Client send:" + Arrays.toString(nums));
    }
}

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

Но это приведет к тому, что IllegalMonitorStateException: объект не будет заблокирован потоком до notifyAll ().Таким образом, кажется, что он пытается уведомить, но отправляющий поток не ждет.Но я не знаю, как решить эту проблему.Я также думаю, что не понимаю, как использовать wait () и notify () в практике.

Надеюсь, один из вас, ребята, поможет мне решить эту глупую проблему; D

...