Вот логика. предположим, что мы хотим запустить калькулятор в окнах с помощью java:
Process p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "calc.exe");
Попробуйте что-то вроде этого:
private final Set<String> runningOperations = Collections.synchronizedSet(new HashSet<>());
private final Object lock = new Object();
@Async
public void analyzeData(User user, List<String> data) throws Exception {
synchronized (lock) {
if (runningOperations.contains(user.company))
return;
runningOperations.add(user.company);
}
try {
boolean operationResult = performLongOperation(data);
if (operationResult) {
log.info("Long operation ended successfully");
} else {
log.error("Long operation failure");
}
} finally {
runningOperations.remove(user.company);
}
}
Вы можете использовать Semaphore
, чтобы ограничить количество потоков, обращающихся к ресурсу.
Поскольку вы хотите, чтобы пользователи из одной компании одновременно обращались к вашей функции анализа, вам следует создать семафор для каждой компании:
// Init on startup
// Key should be a unique identifier to a company, I assume the `String company` as key, you should adjust as your real requirement
static final Map<String, Semaphore> COMPANY_ENTRANT = new ConcurrentHashMap<>();
// for each company
COMPANY_ENTRANT.put(companyId, new Semaphore(1));
Теперь в вашей службе:
@Async
public void analyzeData(User user, List<String> data) {
Semaphore entrant = COMPANY_ENTRANT.get(user.getCompany());
try {
entrant.acquire();
try {
boolean operationResult = performLongOperation(data);
if (opeartionResult) {
log.info("Long operation ended successfully")
} else {
log.error("Long operation failure")
}
} finally {
entrant.release();
}
} catch(InterruptedException e) {
...
}
}
Если вам нужна ленивая инициализация карты COMPANY_ENTRANT
, вы можете использовать putIfAbsent
:
Semaphore entrant = COMPANY_ENTRANT.putIfAbsent(user.getCompany(), new Semaphore(1));
COMPANY_ENTRANT.putIfAbsent
вернет null
, если ранее не было значения на карте. COMPANY_ENTRANT.computeIfAbsent(user.getCompany(), c -> new Semaphore(1))
должен работать
– alaster
13 July 2018 в 13:14