等等&在不同的Classes方法之间通知

时间:2016-11-23 22:49:01

标签: java multithreading javafx wait notify

虽然我的实际问题有所不同,但解决以下问题对我有帮助。  我用scenebuilder构建了一个简单的javafx应用程序。我想通过我的应用程序中的textField从用户那里获取输入,然后在另一个类中打印一个Say,类A.如何在A类中创建一个线程,等到我的另一个guicontroller从用户获取值后通知。我想在一个循环中这样做。

准确,如何在不同类的线程中使用wait和notify?

请原谅我的疑问。 thnx提前

已编辑:我的实际计划是构建聊天信使。我有一个线程,在用户输入后,将转发给收件人。用户将在textField中输入输入,该输入将在guicontroller中处理。

我希望我的guiController通知正在等待发送消息的线程。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

理论上你可以这样做

@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();
}

然而,有更容易的方法来实现这种效果:

BlockingQueue

此类适用于此确切场景:消费者在必要时等待制作人。

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) {
    }

});

使用ExecutorService

此类只允许您发布任务以将信息发送到负责安排和执行任务的ExecutorService。您只需为每条消息提交一个任务即可。

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();
}

请注意,有不同的执行程序可用于调整计划和使用多个线程。