У меня странная архитектура синхронизации, и я ищу элегантное решение.У меня уже было решение, но я не могу ничего сказать о его обоснованности, а также о том, что оно немного уродливо.Так что вот в чем проблема, надеюсь, кто-то может мне помочь.
Есть две группы задач, которые можно запускать и запускать.У каждой задачи есть свой поток.Эти две группы являются частью одного суперкласса, который занимается синхронизацией.Для простоты я назову эти две группы группой A и группой B.
Условия:
Если выполняются только задачи группы B, они могут выполняться одновременнои они не мешают друг другу.
Если запускается задача группы A *, тогда конструктор для задачи группы B должен завершиться сбоем с исключением.Можно создать любое количество задач группы A, даже если задача группы A уже запущена
Задача группы A не может быть выполнена до тех пор, пока все текущие задачи группы B не будут завершены.(* сверху)
Одновременно может выполняться только 1 задача группы A.Они должны быть в очереди.(Необязательно блокировать задачи группы B между выполнением двух задач группы A, если все еще применяются предыдущие условия)
Я считаю, что мой метод работает, но мне не нравитсяЭто работает из-за множества точек синхронизации, которые он использует, и из-за того, что я сплю, ожидая счетчика.В любом случае код будет ниже
public abstract class LockableTask<Params> extends AsyncTask {
private final boolean groupA;
private static Boolean locked = false;
private static final Semaphore semLock = new Semaphore(1);
private static int count = 0;
public LockableTask(boolean groupA) {
this.groupA = groupA;
synchronized (locked) {
if (locked && !groupA) {
throw new InputException("We are locked, please wait");
}
}
}
@Override
protected final AsyncReturn doInBackground(Params... params) {
if (!groupA) {
synchronized (locked) {
count++;
}
}
try {
if (groupA) {
semLock.acquireUninterruptibly();
synchronized (locked) {
locked = true;
}
while (true) {
synchronized (locked) {
if (count == 0) {
break;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
return runInBackground(params);
} finally {
synchronized (locked) {
if (groupA) {
locked = false;
} else {
count--;
}
}
if (groupA) {
semLock.release();
}
}
}
protected abstract AsyncReturn runInBackground(Params... params);
}
Если у кого-то есть более хорошее решение, даже если оно будет чуть лучше, это будет здорово