Общее·количество·просмотров·страницы

Java Dev Notes - разработка на Java (а также на JavaScript/Python/Flex и др), факты, события из АйТи

суббота, 15 марта 2014 г.

Семафоры в Java: реализация простого семафора

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

Комментариев нет:

Отправить комментарий

Постоянные читатели