Семафор используется для обмена сигналами между потоками, или же для охраны критической секции. Их также можно использовать и вместо локов. Несмотря на то, что в JDK уже реализован семафор (java.util.concurrent.Semaphore), полезно будет самим реализовать этот объект.
Итак, у нашего семафора будет всего лишь два метода: take, release. Соответственно, простейшая реализация будет такой:
public class SimpleSemaphore {
boolean taken = false;
public synchronized void take() {
this.taken = true;
this.notify();
}
public synchronized void release() throws InterruptedException {
while (!this.taken) wait();
this.taken = false;
}
}
Теперь давайте рассмотрим программу, которая использует семафор для обмена сигналами. У нас будет два потока: SignalSender, SignalReceiver, которые будут посылать друг другу сигналы. Вот код:
public class Main {
public static void main(String[] args) throws InterruptedException {
SimpleSemaphore semaphore = new SimpleSemaphore();
new Thread(new SignalSender(semaphore)).start();
Thread.currentThread().sleep(2000);
new Thread(new SignalReceiver(semaphore)).start();
}
static class SignalSender implements Runnable {
private final SimpleSemaphore semaphore;
public SignalSender(SimpleSemaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
System.out.println("[SignalSender] run");
while (true) {
try {
doSomeWork();
semaphore.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void doSomeWork() throws InterruptedException {
System.out.println("[SignalSender] do some work");
Thread.sleep(500);
}
}
static class SignalReceiver implements Runnable {
private final SimpleSemaphore semaphore;
public SignalReceiver(SimpleSemaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
System.out.println("[SignalReceiver] run");
while (true) {
try {
semaphore.release();
doSomeWork();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void doSomeWork() throws InterruptedException {
System.out.println("[SignalReceiver] do some work");
Thread.sleep(700);
}
}
}
Посмотрим на вывод консоли:
[SignalSender] run [SignalSender] do some work [SignalSender] do some work [SignalSender] do some work [SignalSender] do some work [SignalSender] do some work [SignalReceiver] run [SignalReceiver] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalReceiver] do some work [SignalSender] do some work [SignalSender] do some work [SignalReceiver] do some workМы видим, как потоки обмениваются сигналами, при этом они ждут друг друга, и начинают работу, только получив соответствующий сигнал от семафора.
Комментариев нет:
Отправить комментарий