Используя семафор, вы можете запускать асинхронные задачи по порядку.В следующем примере планируются действия с использованием пула потоков:
public class SemaphoreSample {
static class MyObject {
private final int waitTime;
private final String name;
MyObject(int waitTime, String name) {
this.waitTime = waitTime;
this.name = name;
}
void doSomething(Semaphore s) {
try {
s.acquire();
TimeUnit.SECONDS.sleep(waitTime);
System.out.println(String.format("%s did something after %ds", name, waitTime));
s.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
Random rd = new Random();
boolean firstInFirstOutOrder = true;
Semaphore s = new Semaphore(1, firstInFirstOutOrder);
for (int i = 0; i < 10; i++) {
MyObject o = new MyObject(rd.nextInt(4), String.format("#%d", i));
threadPool.submit(() -> o.doSomething(s));
}
threadPool.shutdown();
}
}
Когда предполагается выполнение асинхронного действия, он сначала проверяет семафор на наличие доступного разрешения.Если оно доступно, действие выполняется немедленно.В противном случае он ожидает завершения других действий.Семафор гарантирует порядок «первым пришел - первым вышел» для запланированных действий.
Вывод для приведенного выше примера выглядит следующим образом:
#0 did something after 1s
#1 did something after 0s
#2 did something after 0s
#3 did something after 0s
#4 did something after 3s
#5 did something after 1s
#6 did something after 3s
#7 did something after 0s
#8 did something after 1s
#9 did something after 2s
РЕДАКТИРОВАТЬ : Обычно это не такразрешено блокировать поток пользовательского интерфейса, поэтому s.acquire()
не должен вызываться потоком пользовательского интерфейса.Вместо этого вы можете сделать что-то вроде:
void scheduleUiUpdate(Runnable r) {
threadPool.submit(() -> {
try {
semaphore.acquire();
SwingUtilities.invokeAndWait(r);
semaphore.release();
} catch (Exception e) {
e.printStackTrace();
}
});
}
Обратите внимание, что порядок FIFO гарантируется при вызове конструктора семафора с флагом fair , установленным как true .