- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
已编辑:添加了答案中的解决方案。
因此,我构建了经典的多线程程序,其中 2 个线程(生产者和消费者)从同一个列表中读取数据。我确实通过让我的消费者线程不断轮询列表来使其正常工作,但这效率低下,并且给我带来了一些其他问题。所以我想我应该尝试等待并通知。我的两个线程在下面的代码中使用相同的缓冲区引用:
缓冲区:
public class Buffer {
private Queue<Character> result;
public Buffer() {
System.out.println("Buffer");
result = new LinkedList<Character>();
}
public void addChar(char c) {
result.add(c);
}
public char readChar() {
return (char) result.remove();
}
public boolean isEmpty() {
return result.isEmpty();
}
}
制作人
public class Producer implements Runnable {
private Buffer buffer;
private Callback callback;
private String input;
public Producer(Callback callback, Buffer buffer, String input) {
this.callback = callback;
this.buffer = buffer;
this.input = input;
}
@Override
public void run() {
System.out.println("producer started");
synchronized (buffer) {
char[] array = input.toCharArray();
for (int i = 0; i < array.length; i++) {
buffer.addChar(array[i]);
System.out.println("Adding--------- data");
callback.returnData("Added " + array[i]);
buffer.notifyAll();
}
}
}
}
消费者
public class Consumer implements Runnable {
private Callback callback;
private Buffer buffer;
public Consumer(Callback callback, Buffer buffer) {
this.callback = callback;
this.buffer = buffer;
}
@Override
public void run() {
System.out.println("consumer started");
try {
synchronized (buffer) {
while (true) {
if (buffer.isEmpty()) {
System.out.println("Queue is empty ");
buffer.wait();
}
if (!buffer.isEmpty()) {
System.out.println("Reading data");
callback.returnData(" Retrieved " + String.valueOf(buffer.readChar()));
} else {
callback.returnData("Waiting");
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我想要做的是每次生产者线程添加一个元素时,它应该通知我的消费者线程现在可以从缓冲区读取。问题是,直到所有数据都添加完毕后,它才会被唤醒。这是我从控制台得到的结果:
buffer initiated
producer started
consumer started
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Adding--------- data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Reading data
Queue is empty
现在,我真正想要的是:“添加数据”、“读取数据”、“添加数据”等等。
最佳答案
将同步
block 与您希望等待
和通知
的同一对象一起使用。只需将 synchronized
关键字放入方法签名中,您就可以锁定 this
(当前对象),但当您调用 wait
和 notify 时
在缓冲区
上,因此您需要在缓冲区
上进行同步
block 。
您应该如下所示放入方法 block 中,并从methid签名中删除synchronized
关键字。
synchronized (buffer) {
// call notify ,( prefer notifyAll.) on buffer
}
和类似的等待 block 。
以下是您可以尝试的更改,
public class Producer implements Runnable {
private Buffer buffer;
private Callback callback;
private String input;
public Producer(Callback callback, Buffer buffer, String input) {
this.callback = callback;
this.buffer = buffer;
this.input = input;
}
@Override
public void run() {
synchronized (buffer) {
char[] array = input.toCharArray();
try {
for (int i = 0; i < array.length; i++) {
buffer.addChar(array[i]); // production done,
// 1. now notify the consumer thread and
// 2. wait till consumer consumes and notifies.
System.out.println("Adding--------- data");
callback.returnData("Added " + array[i]);
buffer.notifyAll(); // 1. notify done [ consumer notified , this will make consumer get awake from wait state and try to re aquire the lock]
buffer.wait(); //2. waiting for notification from consumer thread.
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Consumer implements Runnable {
private Callback callback;
private Buffer buffer;
public Consumer(Callback callback, Buffer buffer) {
this.callback = callback;
this.buffer = buffer;
}
@Override
public void run() {
try { // having try catch outside will enable you to call interrupt on
// the Thread to stop it
synchronized (buffer) {
// though we check for interrupt flag but in case thread is
// interrupted while waiting, and InterruptedException is
// thrown, the flag will be cleared, hence we need to put try
// catch block outside, other option is to put it inside and make thread true again from catch block.
while (!Thread.currentThread().isInterrupted()) {
if (!buffer.isEmpty()) {
System.out.println("Reading data");
callback.returnData(" Retrieved " + String.valueOf(buffer.readChar())); // consumption done, now
// 1. Notify the consumer thread
// 2. Wait till more production is done
buffer.notifyAll(); // 1. Consumer thread will get this notification and it will get in awakened state. It will try to aquire the lock on Buffer object.
} else {
System.out.println("Queue is empty ");
callback.returnData("Waiting");
}
buffer.wait(); // 2. wait until more production is done and producer notifies after production
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
关于java - 我的线程无法唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40617041/
我正在阅读雷姆齐教授的OSTEP书 http://pages.cs.wisc.edu/~remzi/OSTEP/ 我只能部分理解以下代码如何导致唤醒/等待竞态条件。(该代码摘自书籍一章。 http:/
我目前正在构建一个应用程序,如果我的 android 手机处于锁定状态,我想在收到任何通知时避免屏幕亮起。 我正在尝试找到解决方案,但我找不到任何方法。 我在 switch.setOnCheckedC
有没有办法以编程方式进入 BIOS 并为支持 LAN 唤醒功能的机器打开该功能? 理想情况下,解决方案应该是跨 BIOS,但使用单独的解决方案来打击每个主要供应商也是可以的。 最佳答案 BIOS 配置
我有大量的 Azure 数据库,目前有 6 个,但随着时间的推移,这个数量将会增加。 数据库的访问频率很低,因此为了节省成本,它们被设置为 1 小时后自动休眠。 我需要在 Access 中连接到一个或
我有一个已纳入消费计划的现有 Azure Function 我正在编写另一个函数来调用它 现有函数运行后,它会处理存储帐户中的文件。 为了处理我的存储帐户中的文件,我们必须手动进入门户并通过导航“唤醒
我有一个已纳入消费计划的现有 Azure Function 我正在编写另一个函数来调用它 现有函数运行后,它会处理存储帐户中的文件。 为了处理我的存储帐户中的文件,我们必须手动进入门户并通过导航“唤醒
我想使用方法 wakeUp电源管理器。Eclipse (ADT) 不调整此方法。但是对面的“goToSleep”就没有问题了: PowerManager pm = (PowerManager) MyA
我有以下线程池。 #include #include #include #include #include #include #include // remove me (only fo
我写了一个Java程序,它分析其他程序。执行可能需要很长时间(=几天)。现在(三天后),我遇到了问题,我的程序/进程正在 sleep (S)。它仍然分配了 50% 的内存,有时会打印新的输出,但 to
我有一个很简单的问题。 我们使用 BackgroundAgents( Periodic agents ) 来执行一些后台任务,这些任务需要 WiFi(Internet) 连接才能执行 HttpWebR
我读了一些其他帖子,但没有找到我正在寻找的确切答案,所以我希望有人能给出一些澄清。 我有一个程序会运行一段时间。我有一些在后台运行的线程来执行各种任务,为了简单起见,让我们想想 3 个线程。 Thre
我的后台服务正在尽快将消息发送到本地服务器。每条消息通常需要大约 30 毫秒。但是,当手机处于 sleep 模式时,大约需要 400 毫秒到 1000 毫秒(使用“正确”的 Wifi 策略关闭屏幕)
嘿,我需要在某个时间唤醒我正在 sleep 的 Android 设备。有什么建议吗? 附:唤醒:打开显示屏并可能解锁手机 最佳答案 唤醒屏幕: PowerManager pm = (PowerMana
我们有一个用 C# 编写的 Windows 服务。该服务会生成一个执行此操作的线程: private void ThreadWorkerFunction() { while(false == _s
在scala中,我如何告诉线程: sleep t秒钟,或直到收到消息?也就是说,最多只能睡t秒钟,但是如果t尚未结束,您会醒来,并且您会收到一条特定的消息。 最佳答案 或者,您可以使用条件变量。 va
我发现我们可以在 Awake() 或 Start() 中初始化变量,并且 Awake() 将在 之前调用开始()。 我们应该什么时候在Awake和Start中进行初始化才能获得最佳性能? 最佳答案 通
在 Windows Azure 辅助角色中处理“紧急”消息的最佳方式是什么? 我有一个启动的辅助角色,执行无限 while(true) 循环,并在此循环中: 读取队列中是否有消息 处理它们并删除它们
你好,我已经调试了我的代码一整天,但我就是看不出哪里可能出错。 我在主线程上使用 SerialPortEventListener,在工作线程中我有一个与服务器通信的客户端套接字。由于此工作线程到达re
我想知道线程何时从某个条件中唤醒我在消费者线程上有这样的东西 while(true) { std::unique_lock gu
我希望这个问题适合 SE,但如果不适合,请告诉我可以将其移动到哪里,我会很乐意这样做。我目前正在构建一个 iOS 应用程序,需要在发出“匹配预订请求”时唤醒设备/中断当前应用程序,我正在寻找的行为类似
我是一名优秀的程序员,十分优秀!