Как сохранить JVM во время прослушивания изменений в буфере обмена?

Я пишу программу, которая слушает изменения в буфере обмена и распечатывает изменения в stdout (это всего лишь тест для большой программы). Проблема заключается в том, что, когда основной поток завершает работу, JVM завершается, и никакие события не поступают в прослушиватель. Как я могу сделать, чтобы JVM работал во время прослушивания буфера обмена?

Мой код выглядит так:

public class Test {

    public static void main(String[] args) {

        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();

        cb.addFlavorListener(new FlavorListener() {
            @Override
            public void flavorsChanged(FlavorEvent e) {
                System.out.println(e);
            }
        });

    } 

}

Спасибо!

3 ответа

Решение

Как я могу сделать, чтобы JVM работал во время прослушивания буфера обмена?

Я не понимаю, как бы вы сказали программе прекратить прослушивание буфера обмена надлежащим образом.

Я бы просто распечатал какое-то сообщение, используя стандартный вывод с указанием клавиши для выхода из программы, а затем вызвав сканер или аналог для проверки ввода. Таким образом, вы получите 2 важных пункта:

  1. Нить не умирает сразу, так как сканер выполняет часть ожидания, которую, я думаю, вы ищете.
  2. Пользователи получают контроль над жизненным циклом потока, поэтому они могут завершить его, когда захотят надлежащим образом

Я бы просто позволил основному потоку спать:

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;

public class Test {

    public static void main(String[] args) throws InterruptedException {

        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();

        cb.addFlavorListener(new FlavorListener() {
            @Override
            public void flavorsChanged(FlavorEvent e) {
                System.out.println(e);
            }
        });

        // sleep forever
        Object o = new Object();
        synchronized (o) {
            o.wait();
        }
    } 
}

Важно поддерживать по крайней мере один (не-deamon) поток живым, чтобы ваше приложение работало. Живой поток может быть:

  1. Основная нить, уложить спать
  2. Новая тема, уложить спать
  3. Любая ветка приложения awt/swing, которая обычно остается в живых, пока есть хотя бы один нераспределенный элемент
  4. Любой другой поток, прослушивание любого интерфейса (ожидание System.in HTTP-запрос или просто что-нибудь)

Что касается механизма сна, вот мои три разные техники:

  1. Никогда не делайте этого, он будет загружать ваш процессор:

    for(;;);
    
  2. Намерение этого кода ясно видно:

    for(;;) Thread.sleep(Long.MAX_VALUE);
    
  3. Более элегантный:

    Object o = new Object();
    synchronized (o) {o.wait();}
    

Смотрите, как вы вешаете поток в Java в одну строку? для обсуждения о сне.

Попробуй это:

public static void listen() throws InterruptedException {
    Thread t = new Thread (new Runnable(){

        @Override
        public void run() {
            Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
            Transferable contents = cb.getContents(null);
            cb.addFlavorListener(new FlavorListener() {
                @Override
                public void flavorsChanged(FlavorEvent e) {
                    try {
                        System.out.println("Got Data:"+(String)contents.getTransferData(DataFlavor.stringFlavor));
                    } catch (UnsupportedFlavorException | IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            });
        }
    });
    t.setDaemon(true);
    t.start();

    while (true)
        Thread.sleep(Long.MAX_VALUE);
}
Другие вопросы по тегам