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
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. 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.