java - 试图理解可重入锁条件
问题描述
我正在阅读这篇文章中的@Ashish Lahoti 评论:https : //stackoverflow.com/a/64077645/15456334 在“codingnconcepts”网页中,我正在准备获得一致的输出,例如:
ping 1
pong 1
ping 2
pong 2
.
.
.
ping 500
pong 500
总是“ping”然后“pong”不可能得到两个相同的词 ping ping 或 pong pong。
但是,如果我将时间重复次数更改为 500 并更改“conditionMet.await(2, TimeUnit.SECONDS);”中的时间 到 0 "conditionMet.await(0, TimeUnit.SECONDS):" 我得到下一个输出:
ping 1
pong 1
ping 2
pong 2
.
.
.
Ping 493
Ping 494
Ping 495
Ping 496
Ping 497
Ping 498
Ping 499
Ping 500
正如您在输出中看到的那样,存在 ping ping 重复。
我使用等待和通知方法并且输出总是可以的,我有预期的输出:
package pingponghilos;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Principal {
public static void main(String[] args) {
Runnable ping = new PingPong("PING");
Runnable pong = new PingPong("pong");
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(ping);
executorService.submit(pong);
System.out.println("hola desde el main");
}
}
class PingPong implements Runnable {
private static final Object locker = new Object(); // Locker util
private String name;
public PingPong(String name) {
this.name = name;
}
@Override
public void run() {
while (true) {
synchronized (locker) {
System.out.println(name);
locker.notifyAll();
try {
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
但我试图理解可重入锁定条件以实现与使用 wait() 和 notify() 相同的情况。
有什么建议么?提前致谢。
解决方案
我这样做了:
package pack_20;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class PingPongTest {
// Objeto usado para el bloqueo
public static final ReentrantLock locker = new ReentrantLock(true);
public static void main(String[] args) {
Condition c = locker.newCondition();
PingPong ping = new PingPong("PING", c);
PingPong pong = new PingPong("pong", c);
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> futurePing = executorService.submit(ping);
Future<Integer> futurePong = executorService.submit(pong);
System.out.println("Fin del main");
}
}
class PingPong implements Callable<Integer> {
private int counter = 0;
private final String name;
private final Condition condition; // Condition usada para la instancia de ReentrantLock
private static AtomicBoolean canSayPing = new AtomicBoolean();
public PingPong(String name, Condition condition) {
this.name = name;
this.condition = condition;
}
@Override
public Integer call() throws Exception {
for (int i = 1; i <= 500; i++) {
if (name.equalsIgnoreCase("ping")) {
sayPing();
} else {
sayPong();
}
++counter;
}
return counter;
}
public void sayPing() throws InterruptedException {
PingPongTest.locker.lock();
try {
while (!canSayPing.get()) {
condition.await(0, TimeUnit.SECONDS);
}
System.out.println(name);
canSayPing.set(false);
condition.signal();
} finally {
PingPongTest.locker.unlock();
}
}
public void sayPong() throws InterruptedException {
PingPongTest.locker.lock();
try {
while (canSayPing.get()) {
condition.await(0, TimeUnit.SECONDS);
}
System.out.println(name);
canSayPing.set(true);
condition.signal();
} finally {
PingPongTest.locker.unlock();
}
}
}
输出:总是如我所愿。
PING
pong
PING
pong
PING
pong
PING
pong
PING
.
.
.
PING
pong
PING
pong
PING
pong
PING
pong
PING
但我认为这不是一个好的解决方案。
推荐阅读
- ios - Strava 等应用程序如何在 iPhone 上继续在后台运行?
- android - AppCompatButton 子类具有透明背景
- docker - Hyperledger Fabric:无法将交易“xxx”的对等响应发送给订购者
- ssh - Ansible 无法构造所需的 ssh 命令
- scala - 检查rabbitMQ消息是否路由成功
- java - 导致 libplayer.so 的 APK 崩溃的错误
- javascript - 使用正则表达式和 .replace() 在字符串中动态查找短语
- javascript - React Native 动态 StackNavigator
- sql-server - 尝试从代理作业加载超过 50K 记录时,SSIS 包挂起
- arrays - RuntimeWarning:在 double_scalars 中遇到除以零