В моем приложении для 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