Метод signal
Метод signal класса Condition пробуждает
один поток, который в данный момент ожидает на этом
условии. Если таких потоков несколько, выбирается
один из них. Метод не принимает параметров и ничего
не возвращает. Перед вызовом метода поток должен
захватить блокировку Lock, связанную с данным
условием, иначе будет выброшено исключение
IllegalMonitorStateException.
Метод signal является аналогом метода
notify класса Object, но работает
в связке с Condition и Lock вместо
встроенной синхронизации. Пробуждённый поток
не начнёт выполняться сразу - ему ещё нужно
дождаться освобождения блокировки.
Синтаксис
condition.signal()
Пример
Давайте создадим условие и разбудим ожидающий
поток с помощью signal:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Thread waiter = new Thread(() -> {
lock.lock();
try
{
System.out.println("waiting");
condition.await();
System.out.println("awakened");
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
finally
{
lock.unlock();
}
});
waiter.start();
Thread.sleep(100);
lock.lock();
try
{
condition.signal();
}
finally
{
lock.unlock();
}
waiter.join();
}
}
Результат выполнения кода:
"waiting"
"awakened"
Пример
Давайте посмотрим, что произойдёт, если вызвать
signal без захвата блокировки:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Main
{
public static void main(String[] args)
{
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
try
{
condition.signal();
}
catch (IllegalMonitorStateException e)
{
System.out.println("exception caught");
}
}
}
Результат выполнения кода:
"exception caught"
Пример
Давайте разбудим один поток из нескольких
ожидающих с помощью signal:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Runnable task = () -> {
lock.lock();
try
{
condition.await();
System.out.println(Thread.currentThread().getName());
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
finally
{
lock.unlock();
}
};
Thread t1 = new Thread(task, "t1");
Thread t2 = new Thread(task, "t2");
t1.start();
t2.start();
Thread.sleep(100);
lock.lock();
try
{
condition.signal();
}
finally
{
lock.unlock();
}
t1.join();
lock.lock();
try
{
condition.signal();
}
finally
{
lock.unlock();
}
t2.join();
}
}
Результат выполнения кода:
"t1"
"t2"
Смотрите также
-
метод
await,
который заставляет поток ожидать на условии -
метод
signalAll,
который пробуждает все ожидающие потоки -
класс
Condition,
который представляет условие ожидания -
класс
ReentrantLock,
который создаёт блокировку и условие