Exemples de sémaphore Java

Exemples de sémaphore Java

En Java, nous pouvons utiliserSemaphore pour limiter le nombre de threads pour accéder à une certaine ressource.

1. Qu'est-ce que le sémaphore?

En bref, un sémaphore maintient un ensemble de permis (tickets), chaqueacquire() prendra un permis (ticket) du sémaphore, chaquerelease() retournera le permis (ticket) au sémaphore. Si les permis (tickets) ne sont pas disponibles,acquire() bloquera jusqu'à ce qu'il y en ait un.

    // 5 tickets
    Semaphore semaphore = new Semaphore(5);

    // take 1 ticket
    semaphore.acquire();

    // 4
    semaphore.availablePermits();

    // return back ticket
    semaphore.release();

    // 5
    semaphore.availablePermits();

2. Java Semaphore

Un exemple de sémaphore Java pour limiter le nombre de tâches en cours d'exécution dansExecutorService. Dans cet exemple, 5 tâchesCallable sont soumises àExecutorService, mais seules 2 tâches sont exécutées simultanément.

TaskLimitSemaphore.java

package com.example.concurrency.synchronizer.semaphore;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

// Throttle task submission
public class TaskLimitSemaphore {

    private final ExecutorService executor;
    private final Semaphore semaphore;

    public TaskLimitSemaphore(ExecutorService executor, int limit) {
        this.executor = executor;
        this.semaphore = new Semaphore(limit);
    }

    public  Future submit(final Callable task) throws InterruptedException {

        semaphore.acquire();
        System.out.println("semaphore.acquire()...");

        return executor.submit(() -> {
            try {
                return task.call();
            } finally {
                semaphore.release();
                System.out.println("semaphore.release()...");
            }
        });

    }

    private static final DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

    public static void main(String[] args) throws InterruptedException {

        ExecutorService executor = Executors.newCachedThreadPool();

        // Only 2 tasks are able to run concurrently
        TaskLimitSemaphore obj = new TaskLimitSemaphore(executor, 2);

        obj.submit(() -> {
            System.out.println(getCurrentDateTime() + " : task1 is running!");
            Thread.sleep(2000);
            System.out.println(getCurrentDateTime() + " : task1 is done!");
            return 1;
        });

        obj.submit(() -> {
            System.out.println(getCurrentDateTime() + " : task2 is running!");
            Thread.sleep(2000);
            System.out.println(getCurrentDateTime() + " task2 is done!");
            return 2;
        });

        obj.submit(() -> {
            System.out.println(getCurrentDateTime() + " task3 is running!");
            Thread.sleep(2000);
            System.out.println(getCurrentDateTime() + " task3 is done!");
            return 3;
        });

        obj.submit(() -> {
            System.out.println(getCurrentDateTime() + " task4 is running!");
            Thread.sleep(2000);
            System.out.println(getCurrentDateTime() + " task4 is done!");
            return 4;
        });

        obj.submit(() -> {
            System.out.println(getCurrentDateTime() + " task5 is running!");
            Thread.sleep(2000);
            System.out.println(getCurrentDateTime() + " task5 is done!");
            return 5;
        });

        executor.shutdown();
    }

    private static String getCurrentDateTime() {
        return sdf.format(new Date());
    }
}

Sortie

semaphore.acquire()...
semaphore.acquire()...
2018/12/06 18:45:22 : task1 is running!
2018/12/06 18:45:22 : task2 is running!
2018/12/06 18:45:24 : task1 is done!
2018/12/06 18:45:24 task2 is done!
semaphore.release()...
semaphore.acquire()...
semaphore.release()...
semaphore.acquire()...
2018/12/06 18:45:24 task3 is running!
2018/12/06 18:45:24 task4 is running!
2018/12/06 18:45:26 task4 is done!
2018/12/06 18:45:26 task3 is done!
semaphore.acquire()...
semaphore.release()...
semaphore.release()...
2018/12/06 18:45:26 task5 is running!
2018/12/06 18:45:28 task5 is done!
semaphore.release()...

3. Mutex

En bref, toujoursnew Semaphore(1), un seul thread est autorisé à accéder à une certaine ressource.

PrintSequenceCallable.java

package com.example.concurrency.synchronizer.semaphore;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SshLoginSemaphore {

    private final Semaphore mutex;

    // only 1 user is allow
    public SshLoginSemaphore() {
        this.mutex = new Semaphore(1);
    }

    private void ssh(String user) throws InterruptedException {

        mutex.acquire();
        System.out.println(getCurrentDateTime() + " : " + user + " mutex.acquire()");

        Thread.sleep(2000);

        mutex.release();
        System.out.println(getCurrentDateTime() + " : " + user + " mutex.release()");

    }

    private static final DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

    public static void main(String[] args) {

        ExecutorService executor = Executors.newFixedThreadPool(5);

        SshLoginSemaphore task = new SshLoginSemaphore();

        // submit 3 tasks
        executor.submit(() -> {
            try {
                task.ssh("example");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        executor.submit(() -> {
            try {
                task.ssh("yflow");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        executor.submit(() -> {
            try {
                task.ssh("zilap");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        executor.shutdown();

    }

    private static String getCurrentDateTime() {
        return sdf.format(new Date());
    }

}

Sortie

Vérifiez le temps (secondes), un seul thread est autorisé, unacquire() et unrelease()

2018/12/06 18:54:25 : example mutex.acquire()
2018/12/06 18:54:27 : yflow mutex.acquire()
2018/12/06 18:54:27 : example mutex.release()
2018/12/06 18:54:29 : zilap mutex.acquire()
2018/12/06 18:54:29 : yflow mutex.release()
2018/12/06 18:54:31 : zilap mutex.release()

Télécharger le code source