Я полагаю, вы ищете способ получить блокировку, если это возможно, и сделать что-то еще, если это платно.
Вы можете сделать это с помощью ReentrantLock#tryLock
.
Метод:
Получает блокировку только в том случае, если она не удерживается другим потоком во время вызова.
И он возвращает:
true
если блокировка была свободна и была получена текущим потоком, или блокировка уже удерживалась текущим потоком; и false
иначе
Вот модифицированная версия кода из вопроса:
- если блокировка для первой задачи свободна, поток запустит первую задачу
- иначе он запустит его после второго
Processor.java
:
public class Processor extends Thread {
private static final Lock lock1 = new ReentrantLock();
private static final Lock lock2 = new ReentrantLock();
@SneakyThrows
private void doJob1() {
System.out.println(Thread.currentThread().getName() + " doing job1");
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + " completed job1");
}
@SneakyThrows
private void doJob2() {
System.out.println(Thread.currentThread().getName() + " doing job2");
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + " completed job2");
}
public void run() {
boolean executedFirst = false;
if (lock1.tryLock()) {
try {
doJob1();
executedFirst = true;
} finally {
lock1.unlock();
}
}
try {
lock2.lock();
doJob2();
} finally {
lock2.unlock();
}
if (!executedFirst) {
try {
lock1.lock();
doJob1();
} finally {
lock1.unlock();
}
}
}
public static void main(String[] args) {
new Processor().start();
new Processor().start();
}
}
Пример вывода:
Thread-1 doing job2
Thread-0 doing job1
Thread-0 completed job1
Thread-1 completed job2
Thread-1 doing job1
Thread-0 doing job2
Thread-1 completed job1
Thread-0 completed job2
Обратите внимание, что вызовы lock
/tryLock
и unlock
заключены в try
/finally
.
Переход в корзины и мячи:
Color.java
:
public enum Color {
RED,
GREEN,
BLUE;
public static Color fromOrdinal(int i) {
for (Color value : values()) {
if (value.ordinal() == i) {
return value;
}
}
throw new IllegalStateException("Unknown ordinal = " + i);
}
}
Basket.java
:
@Data(staticConstructor = "of")
public class Basket {
private final Color color;
// balls that this basket has
private final List<Ball> balls = new ArrayList<>();
private final Lock lock = new ReentrantLock();
}
Ball.java
@Value(staticConstructor = "of")
public class Ball {
Color color;
}
Boy.java
- Каждый мальчик выбирает мяч (
queue.poll()
)
- Бежит к корзине (
baskets.get(color)
одного цвета)
- And depending on behavior when a basket is occupied he:
- throws ball away and tries again (option
a
in code)
- ждет освобождения корзины (опция
b
)
- Обратите внимание, что с опцией
a
некоторые boy
могут закончиться между ними, когда другой выбрасывает ball
, и никто еще не подобрал его (в любом случае, кто-то подберет его и положит в корзину)
@RequiredArgsConstructor
public class Boy implements Runnable {
private final Map<Color, Basket> baskets;
private final Queue<Ball> balls;
@Override
public void run() {
Ball ball;
while ((ball = balls.poll()) != null) {
Color color = ball.getColor();
Basket basket = baskets.get(color);
// a
if (basket.getLock().tryLock()) {
try {
basket.getBalls().add(ball);
} finally {
basket.getLock().unlock();
}
} else {
balls.offer(ball);
}
// b
/*
try {
basket.getLock().lock();
basket.getBalls().add(ball);
} finally {
basket.getLock().unlock();
}
*/
}
}
}
и, наконец, main
:
Queue<Ball> balls = new LinkedBlockingQueue<>();
ThreadLocalRandom.current().ints(0, 3)
.mapToObj(Color::fromOrdinal)
.map(Ball::of)
.limit(1000)
.forEach(balls::add);
Map<Color, Basket> baskets = Map.of(
Color.RED, Basket.of(Color.RED),
Color.GREEN, Basket.of(Color.GREEN),
Color.BLUE, Basket.of(Color.BLUE)
);
List<Thread> threads = IntStream.range(0, 100)
.mapToObj(ignore -> new Boy(baskets, balls))
.map(Thread::new)
.collect(Collectors.toList());
threads.forEach(Thread::start);
for (Thread thread : threads) {
thread.join();
}
baskets.forEach((color, basket) -> System.out.println("There are "
+ basket.getBalls().size() + " ball(-s) in " + color + " basket"));
Пример вывода:
There are 331 ball(-s) in GREEN basket
There are 330 ball(-s) in BLUE basket
There are 339 ball(-s) in RED basket
person
caco3
schedule
05.01.2021