Подтвердить что ты не робот

Threading в Java: как заблокировать объект?

В своем потоке выполняется следующая функция:

private void doSendData()
{
    try {

           //writeToFile(); // just a temporary location of a call
           InetAddress serverAddr = InetAddress.getByName(serverAddress);
           serverAddr.wait(60000);
           //Log.d("TCP", "C: Connecting...");
           Socket socket = new Socket(serverAddr, portNumber);
           socket.setSoTimeout(3000);

               try {
                //Log.d("TCP", "C: Sending: '" + message + "'");
                PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
                String message = packData();
                out.println(message);
                Log.d("TCP", "C: Sent.");
                Log.d("TCP", "C: Done.");
                connectionAvailable = true;

             } catch(Exception e) {
                 Log.e("TCP", "S: Error", e);
                 connectionAvailable = false;

               } finally {
                  socket.close();
                  announceNetworkAvailability(connectionAvailable);
                }

         } catch (Exception e) {
              Log.e("TCP", "C: Error", e);
              announceNetworkAvailability(connectionAvailable);
         }
}

Когда выполнение достигает строки serverAddr.wait(60000), он выдает исключение:

java.lang.IllegalMonitorStateException: object not locked by thread before wait()

Кто-нибудь знает, как заблокировать объект или функцию, чтобы предотвратить concurrency? Я попытался добавить объект Lock:

private final Lock lock = new ReentrantLock();

и строка

boolean locked = lock.tryLock();

в начале функции, но это не сработало.

4b9b3361

Ответ 1

Чтобы вызвать wait() для объекта, вы должны удерживать синхронизированную блокировку этого объекта (хотя блокировка фактически освобождается, пока поток ожидает):

synchronized (serverAddr) {
  serverAddr.wait();
}

Я должен признать, что поэтому вы хотите сделать это, чтобы это меня озадачило...

Ответ 2

Возможно, метод, который вы ищете, Thread.sleep(long)? Этот метод будет ждать (как в случае остановки выполнения потока) за указанное время в миллисекундах до возобновления.

object.wait(long) (это то, что вы используете) делает что-то совершенно другое. Он ждет другого объекта из другого потока, чтобы уведомить его (т.е. Отправить его как сообщение о пробуждении) и будет ждать не более указанного количества миллисекунд. Учитывая код, который вы опубликовали, я очень сомневаюсь, что это то, что вы действительно хотите.

Если Thread.sleep() не то, что вы хотите, тогда вы должны использовать синхронизированный блок, как упомянуто другими плакатами.

Ответ 3

Я всегда сжимаю, когда вижу такой код. Сделайте себе одолжение и посмотрите на пакет java.util.concurrent.

Ответ 4

Чтобы избежать этого сообщения об ошибке, используйте ключевое слово synchronized:

synchronized(serverAddr){
  serverAddr.wait(60000);
}

Ответ 5

Вышеуказанные правильные. Вы можете использовать синхронизированный блок кода. Или вы можете создать то, что они называют мьютексом. Мьютекс может быть любым объектом. Многие люди просто используют объект как мьютекс. Затем вы можете заблокировать мьютекс. Любые потоки, желающие получить доступ, должны ждать, пока поток, содержащий мьютекс, освободит его.

Было также предложение Apocalisp. Я также рекомендую вам посмотреть пакет java.util.concurrent.

Ответ 6

В общем случае, когда у вас есть многопоточная программа на Java, вам нужно заблокировать общую переменную с помощью синхронизированного (ключевого слова), тогда в любое время только один поток может получить доступ к общей памяти.

Ответ 7

Ниже код должен работать.

     private final ReentrantLock lock = new ReentrantLock();

     lock.lock();  // block until condition holds
     try {
        serverAddr.wait(60000);
     } finally {
       lock.unlock()
     }
   }

Подробнее см. в этой документации страница.

public void lock()

Получает блокировку.

Приобретает блокировку, если она не удерживается другим потоком и возвращается немедленно, устанавливая значение блокировки блокировки на один.

Если текущий поток уже содержит блокировку, тогда счетчик удержания увеличивается на единицу, и метод немедленно возвращается.

Если блокировка удерживается другим потоком, то текущий поток отключается для целей планирования потоков и находится в состоянии покоя до тех пор, пока блокировка не будет получена, и в это время счет блокировки блокировки будет установлен на один

Обратитесь к этому вопросу SE, чтобы узнать преимущества lock над synchronization:

Синхронизация и блокировка