仅当主事件侦听器更新时,如何将来自主事件侦听器的MesageReceivedEvent与线程内的新变量同步
How to synchronize MesageReceivedEvent from main EventListener with a new variable inside Thread only when it is updated by main's listener
我需要创建一个新线程,当且仅当主 ListenerAdapter 中的 MessageReceivedEvent 更新时,该线程才会执行一个方法,并让线程在变量未更新时休眠。
该线程应该 运行 独立于主线程并且不会停止新请求。
这是话题 class,
private static final class Worker extends Thread {
private volatile boolean running = false;
MessageReceivedEvent event; //this must update along with the listener
private boolean validateData() {
if (//something) {
return true;
}
return false;
}
private void waitForInput() {
boolean hasInput = false;
try {
while (!hasInput) {
hasInput = validateData();
if (!hasInput) {
Thread.sleep(10);
}
}
} catch (InterruptedException iex) {
Thread.currentThread().interrupt();
}
}
@Override
public void run() {
running = true;
while (running) {
waitForInput();
//do something
}
}
}
是一个内class运行由主线程请求,
只有当来自侦听器的实际事件发生变化时,它内部的 MessageReceivedEvent 才必须更新,否则它什么都不做。
测试时,只会根据触发线程的MessageEvent执行,如何让线程收到更新?
public class Listener extends ListenerAdapter {
public static MessageReceivedEvent msgEvnt;
@Override
public void onMessageReceived(MessageReceivedEvent msgEvnt) {
Listener.msgEvnt = msgEvnt;
}
这就是侦听器所做的全部工作,每当有新的消息事件时更新变量。
您可以使用 Condition Variable 来完成此操作。
final ReentrantLock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
private void waitForInput() {
lock.lock();
Listener.msgEvnt = null;
try {
while (Listener.msgEvnt == null)
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
lock.lock();
try {
Listener.msgEvnt = msgEvnt;
condition.signal();
} finally {
lock.unlock();
}
}
See ReentrantLock and Condition
您可以使用 BlockingQueue
final BlockingQueue queue = new ConcurrentBlockingQueue();
private MessageReceivedEvent waitForInput() throws InterruptedException {
return queue.take();
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
queue.put(event);
}
您可以使用 Callback,这是我推荐的。
Consumer<? super MessageReceivedEvent> callback;
private void onInput(Consumer<? super MessageReceivedEvent> callback) {
this.callback = callback;
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
if (this.callback != null)
this.callback.accept(event);
this.callback = null;
}
使用示例:
listener.waitForInput(event -> {
System.out.printf("%#s: %s\n", event.getAuthor(), event.getMessage().getContentDisplay());
});
已提供
我需要创建一个新线程,当且仅当主 ListenerAdapter 中的 MessageReceivedEvent 更新时,该线程才会执行一个方法,并让线程在变量未更新时休眠。 该线程应该 运行 独立于主线程并且不会停止新请求。
这是话题 class,
private static final class Worker extends Thread {
private volatile boolean running = false;
MessageReceivedEvent event; //this must update along with the listener
private boolean validateData() {
if (//something) {
return true;
}
return false;
}
private void waitForInput() {
boolean hasInput = false;
try {
while (!hasInput) {
hasInput = validateData();
if (!hasInput) {
Thread.sleep(10);
}
}
} catch (InterruptedException iex) {
Thread.currentThread().interrupt();
}
}
@Override
public void run() {
running = true;
while (running) {
waitForInput();
//do something
}
}
}
是一个内class运行由主线程请求, 只有当来自侦听器的实际事件发生变化时,它内部的 MessageReceivedEvent 才必须更新,否则它什么都不做。 测试时,只会根据触发线程的MessageEvent执行,如何让线程收到更新?
public class Listener extends ListenerAdapter {
public static MessageReceivedEvent msgEvnt;
@Override
public void onMessageReceived(MessageReceivedEvent msgEvnt) {
Listener.msgEvnt = msgEvnt;
}
这就是侦听器所做的全部工作,每当有新的消息事件时更新变量。
您可以使用 Condition Variable 来完成此操作。
final ReentrantLock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
private void waitForInput() {
lock.lock();
Listener.msgEvnt = null;
try {
while (Listener.msgEvnt == null)
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
lock.lock();
try {
Listener.msgEvnt = msgEvnt;
condition.signal();
} finally {
lock.unlock();
}
}
See ReentrantLock and Condition
您可以使用 BlockingQueue
final BlockingQueue queue = new ConcurrentBlockingQueue();
private MessageReceivedEvent waitForInput() throws InterruptedException {
return queue.take();
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
queue.put(event);
}
您可以使用 Callback,这是我推荐的。
Consumer<? super MessageReceivedEvent> callback;
private void onInput(Consumer<? super MessageReceivedEvent> callback) {
this.callback = callback;
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
if (this.callback != null)
this.callback.accept(event);
this.callback = null;
}
使用示例:
listener.waitForInput(event -> {
System.out.printf("%#s: %s\n", event.getAuthor(), event.getMessage().getContentDisplay());
});
已提供