仅当主事件侦听器更新时,如何将来自主事件侦听器的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());
});

JDA-Utilities

已提供