简体   繁体   English

在不同的类之间等待并通知方法

[英]Wait & Notify among different Classes method

Though my actual problem is bit different , solving the following problem will help me . 尽管我的实际问题有所不同,但解决以下问题将对我有所帮助。 I have built a simple javafx application with scenebuilder . 我已经使用scenebuilder构建了一个简单的javafx应用程序。 I would like to take input from user via a textField in my application and print that one in another class Say, class A. How can i make a thread, in class A, wait until my another guicontroller notify after getting value from user . 我想通过我的应用程序中的textField从用户那里获取输入,并在另一个类中打印该输入,比如说A类。我如何在A类中创建线程,等到从user获取值后另一个guicontroller通知。 I want to do this in a loop. 我想循环执行此操作。

To be precise , How can i use wait and notify among threads in different classes ? 确切地说 ,如何在不同类的线程之间使用等待和通知?

Please pardon me for my scrappy question . 请原谅我棘手的问题。 thnx in advance 提前thnx

Edited: My actual program is to build a chat messenger . 编辑:我的实际程序是构建聊天程序。 Where i have a thread that will , after having the input from user , will forward to recipient . 我有一个线程,在收到用户输入后,该线程将转发给收件人。 User will give input in a textField which will be handled in a guicontroller. 用户将在textField中输入内容,该内容将在guicontroller中处理。

I want my guiController to notify the Thread that is waiting for sending message. 我希望我的guiController通知正在等待发送消息的线程。

How can i do that ? 我怎样才能做到这一点 ?

You could theoretically do it like this 从理论上讲,您可以这样做

@Override
public void start(Stage primaryStage) {
    TextField textField = new TextField();
    List<String> messages = new LinkedList<>();
    Thread thread = new Thread(() -> {
        while (true) {
            String message;
            synchronized (messages) {
                if (messages.isEmpty()) {
                    // empty message queue -> wait
                    try {
                        messages.wait();
                    } catch (InterruptedException ex) {
                        // unknown cause of interrupt -> just try reading the messages anew
                        continue;
                    }
                }
                message = messages.remove(0);
            }
            System.out.println("sending message: " + message);

            try {
                // simulate delay
                Thread.sleep(3000);
            } catch (InterruptedException ex) {
            }
        }
    });
    thread.setDaemon(true);
    thread.start();

    textField.setOnAction(evt -> {
        synchronized (messages) {
            // add new message to queue
            messages.add(textField.getText());

            // notify thread
            messages.notify();
        }
        textField.clear();
    });

    Scene scene = new Scene(textField);

    primaryStage.setScene(scene);
    primaryStage.show();
}

However there are much easier ways to achieve this effect: 但是,有很多更简单的方法可以达到此效果:

BlockingQueue

This class is designed for this exact scenario: a consumer waiting for a producer, if necessary. 此类是针对以下确切情况而设计的:如有必要,消费者等待生产者。

LinkedBlockingQueue<String> messages = new LinkedBlockingQueue<>();
Thread thread = new Thread(() -> {
    while (true) {
        String message;
        try {
            message = messages.take();
        } catch (InterruptedException ex) {
            continue;
        }
        System.out.println("sending message: "+message);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException ex) {
        }
    }
});
thread.setDaemon(true);
thread.start();

textField.setOnAction(evt -> {
    try {
        messages.put(textField.getText());
        textField.clear();
    } catch (InterruptedException ex) {
    }

});

Using a ExecutorService 使用ExecutorService

This class simply allows you to post the task to send the info to a ExecutorService that takes care of scheduling and executing the task. 此类仅允许您发布任务以将信息发送到ExecutorService ,该服务负责安排和执行任务。 You can simply submit one task per message. 您只需为每条消息提交一项任务即可。

private ExecutorService executor;

@Override
public void init() throws Exception {
    executor = Executors.newSingleThreadExecutor();
}

@Override
public void stop() throws Exception {
    executor.shutdownNow();
    // TODO: handle unsent messages or replace with executor.shutdown()
}

private void postMessage(String message) {
    executor.submit(() -> {
        System.out.println("sending message: "+message);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException ex) {
        }
    });
}

@Override
public void start(Stage primaryStage) {
    TextField textField = new TextField();

    textField.setOnAction(evt -> {
        postMessage(textField.getText());
        textField.clear();
    });

    Scene scene = new Scene(textField);

    primaryStage.setScene(scene);
    primaryStage.show();
}

Note that there are different executors available to adjust the scheduling and for using multiple threads. 请注意,可以使用不同的执行程序来调整调度并使用多个线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM