Семафор используется для обмена сигналами между потоками, или же для охраны критической секции. Их также можно использовать и вместо локов. Несмотря на то, что в 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Мы видим, как потоки обмениваются сигналами, при этом они ждут друг друга, и начинают работу, только получив соответствующий сигнал от семафора.
Комментариев нет:
Отправить комментарий