Как складывать входящие данные - PullRequest
1 голос
/ 27 декабря 2011

Каждый раз, когда приходит внутреннее сообщение, я добавляю его в JList, и JList обновляется с помощью fireIntervalAdded.Проблема в том, что за одну секунду может прийти 20 сообщений, и каждое из них вызовет fireIntervalAdded.Я хотел бы собрать все сообщения в List и отправить один большой стек данных в JList.Мое текущее решение, похоже, не работает, оно всегда отправляет одно сообщение вместо одного большого стека:

    private class StackingListener implements MessageListener {
    private List<Message> messages = new LinkedList<Message> ();
    private int waiting = 0;
    @Override
    public void messageReceived(MessageEvent event) {
        stackData(event.getData());
    }

    private void stackData(Message data) {
        messages.add(data);
        if (waiting <= 0) {
            waiting = 3;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(--waiting > 0) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    List<Message> list = new ArrayList<Message>(messages);
                    messages.clear();
                    logger.info("Adding list with size of " + list.size());
                    controller.getListModel().addFullElements(list);
                }
            }).run();
        } else {
            waiting = 3;
        }
    }
}

Я думаю, что я делаю что-то очень неправильно.Идея этого кода состоит в том, чтобы складывать сообщения, пока Thread спит.Но похоже, что Thread.sleep останавливает все, не только текущий поток.

Спасибо

1 Ответ

3 голосов
/ 27 декабря 2011

Вы используете Thread.run (), который просто вызывает метод run () в текущем потоке. То, что вы намеревались использовать, было Thread.start () создает поток и вызывает run () в этом новом потоке.

Однако я бы не стал структурировать такой код вообще. Я полагаю, что более простой способ - использовать очередь.

class StackingListener implements MessageListener, Runnable {
    private final BlockingQueue<Message> messages = new LinkedBlockingDeque<Message>();
    private final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); {
        service.scheduleAtFixedRate(this, 500, 500, TimeUnit.MILLISECONDS);
    }

    @Override
    public void messageReceived(MessageEvent event) {
        messages.add(event.getData());
    }

    @Override
    public void run() {
        final List<Message> list = new ArrayList<Message>();
        messages.drainTo(list);

        logger.info("Adding list with size of " + list.size());
        // add to the GUI component in a thread safe manner.
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                controller.getListModel().addFullElements(list);
            }
        });
    }

    public void stop() {
        service.shutdown();
    }
}
...