>source

저는 Java와 함께 멀티 스레딩을 사용하고 있습니다. 큐에 메시지를 게시할 스레드, 스레드로부터 안전한 blockingQueue, 그리고 스윙으로 QUI를 구현하는 다른 스레드가 있습니다. 대기열이 비어 있는지 여부를 확인할 때마다 그렇지 않은 경우 메시지를 폴링하여 DefaultListModel에 추가하지만 문제는 디스플레이가 업데이트되지 않습니다. 폴링된 메시지가 비어 있지 않은지 확인했습니다. 이것은 code입니다: JList의 구현을 위해

historyListModel= new DefaultListModel<String>();
        historyList= new JList<String>(historyListModel);
        historyList.setAutoscrolls(true);
        JScrollPane historyScroll= new JScrollPane(historyList);
        add(historyScroll, BorderLayout.CENTER);

대기열에 메시지 추가

private BlockingQueue<String> messageRes= new LinkedBlockingQueue<>();
DatagramPacket packet= new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String msgReceived= new String(packet.getData(), 0, packet.getLength());
messageRes.add(msgReceived);

디스플레이를 업데이트할 스레드

private class update implements Runnable{
        @Override
        public void run() {
            while (true){
                if (!messageRes.isEmpty()){
                    historyListModel.addElement(messageRes.poll());
                }
            }
        }
    }

이 스레드는 GUI 메인 창에서 호출됩니다.

new Thread(new update()).start();

몇 가지 테스트를 하기 위해 다음 code를 시도했는데 작동했습니다.


private class update implements Runnable{
        @Override
        public void run() {
            while (true){
                Thread.sleep(1000)
                historyListModel.addElement("hello world);
            }
        }
    }

이전 code를 사용하면 1초마다 디스플레이를 업데이트할 수 있습니다. 오류를 삼각 측량하기 위해 code를 하나 더 시도했습니다.

private class update implements Runnable{
        @Override
        public void run() {
            while (true){
                if (!messageRes.isEmpty()){
                    historyListModel.addElement(messageRes.poll());
                    historyListModel.addElement("hello world);
                }
            }
        }
    }

이전 code로 업데이트된 디스플레이가 없습니다. 아무도 무슨 일이 일어나고 있는지 설명을 제안할 수 있습니까?

감사합니다.

Swing에서 동시성을 확인한 다음 게시 및 프로세스 메서드와 함께 SwingWorker를 사용하여 스레드로부터 안전한 방식으로 JList 모델을 업데이트합니다.

DontKnowMuchBut Getting Better2022-02-08 07:39:12
  • 답변 # 1

    Swing은 스레드로부터 안전하지 않으며 단일 스레드입니다. 즉, 이벤트 디스패칭 스레드 컨텍스트 외부에서 UI를 업데이트하거나 해당 컨텍스트 내에서 장기 실행/차단 호출을 실행해서는 안 됩니다.

    귀하의 경우스윙워커새 메시지에 대한 대기열을 폴링하고출판하다안전한 방식으로 UI로 이동합니다.

    봐...

    자세한 내용은.

    테스트하는 동안 내가 주목한 한 가지는 다음과 같습니다.

    @Override
    public void run() {
        while (true){
            if (!messageRes.isEmpty()){
                historyListModel.addElement(messageRes.poll());
            }
        }
    }
    

    아마도 UI에 과부하가 걸렸을 것입니다.투표다음 요소를 반환하거나없는아무도없는 경우. 그래서 그것은 "와일드 루프"였습니다. 대신, 당신은 아마도가져 가다새 값을 사용할 수 있을 때까지 대기합니다.

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.atomic.AtomicBoolean;
    import javax.swing.DefaultListModel;
    import javax.swing.JFrame;
    import javax.swing.JList;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.SwingWorker;
    public class Main {
        public static void main(String[] args) {
            new Main();
        }
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame= new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
        public class TestPane extends JPanel {
            private JList<String> messageList;
            private DefaultListModel<String> model;
            public TestPane() {
                model= new DefaultListModel<>();
                messageList= new JList<>(model);
                setLayout(new BorderLayout());
                add(new JScrollPane(messageList));
                Consumer consumer= new Consumer();
                Producer producer= new Producer();
                ConsumerWoker worker= new ConsumerWoker(consumer, model);
                worker.execute();
                Thread thread= new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            while (true) {
                                consumer.add(producer.next());
                                Thread.sleep(500);
                            }
                        } catch (InterruptedException ex) {
                        }
                    }
                });
                thread.start();
            }
        }
        public class Producer {
            private List<String> master= Arrays.asList(new String[]{
                "Malachy Keller",
                "Ruqayyah Galvan",
                "Harris Nunez",
                "Nojus Riggs",
                "Joan Mercer",
                "Lynda Solomon",
                "Raiden Fitzpatrick",
                "Sebastian Ahmed",
                "Jo Short",
                "Nabeel Howarth",
                "Maira Garrett",
                "Patrik Knights",
                "Mimi Mcgill",
                "Antonina Villanueva",
                "Kenya Hyde",
                "Aleksander Rigby",
                "Hasan Gilmore",
                "Jessica Mcculloch",
                "Seth Black",
                "Marjorie Brewer",
                "Elliot Gay",
                "Oluwatobiloba Bowman",
                "Domonic Saunders",
                "Braden Hale",
                "Muneeb Rankin",
                "Ruby Tapia",
                "Iris Hines",
                "Afsana Ponce",
                "Beverly Soto",
                "Presley Bloggs",
                "Leopold Goddard",
                "Missy Browne",
                "Deniz Woodcock",
                "Gwion Ferreira",
                "Stanley Mccall",
                "Jayda Christie",
                "Nikhil Plummer",
                "Stacy Crosby",
                "Cally Henry",
                "Lilliana Taylor",
                "Dolcie Navarro",
                "Merryn Reynolds",
                "Annalise Boyce",
                "Anaya Cisneros",
                "Aimie Piper",
                "Celine Pearson",
                "Clayton Battle",
                "Danielle Briggs",
                "Maddison Couch",
                "Jorden Keeling",
                "Iylah Holmes",
                "Bethaney Quintero",
                "Dominique Brett",
                "Rohit Benjamin",
                "Edgar Rodgers",
                "Petra Salgado",
                "Myrtle Deleon",
                "Letitia Sheridan",
                "Wasim Chester",
                "Leela Simpson",
                "Aine Rojas",
                "Ava Mclean",
                "Jerry Caldwell",
                "Fraser Prosser",
                "Callum Vang",
                "Yasmin Ochoa",
                "Gaia Daly",
                "Vanessa Mathews",
                "Scarlett Brook",
                "Rhiann Fox",
                "Nansi Cote",
                "Dwayne Rowley",
                "Junior Lucas",
                "Becky Rush",
                "Lori Guthrie",
                "Safa Reed",
                "Merlin Cartwright",
                "Misbah Trejo",
                "Khaleesi Ellison",
                "Lena Wood",
                "Bluebell Coffey",
                "Sherry Hutton",
                "Abi Delacruz",
                "Kwabena Bright",
                "Anastazja Kumar",
                "Bronwyn Huffman",
                "Atif Burke",
                "Arwen Kirby",
                "Bobbie Noble",
                "Blane Bauer",
                "Zander Sparrow",
                "Marius Wormald",
                "Rajan Perez",
                "Teejay Faulkner",
                "Imaani Rodriquez",
                "Safaa Middleton",
                "Rafael Livingston",
                "Oakley Swan",
                "Samiya Kim",
                "Glen Beasley"
            });
            private List<String> avaliableMessages;
            public Producer() {
                avaliableMessages= new ArrayList<>(100);
            }
            public String next() {
                if (avaliableMessages.isEmpty()) {
                    avaliableMessages.addAll(master);
                }
                return avaliableMessages.remove(0);
            }
        }
        public class Consumer {
            private BlockingQueue<String> messages= new LinkedBlockingDeque<>();
            public void add(String message) {
                messages.add(message);
            }
            public String next() throws InterruptedException {
                return messages.take();
            }
        }
        public class ConsumerWoker extends SwingWorker<Void, String> {
            private AtomicBoolean keepRunning= new AtomicBoolean(true);
            private Consumer consumer;
            private DefaultListModel model;
            public ConsumerWoker(Consumer consumer, DefaultListModel model) {
                this.consumer= consumer;
                this.model= model;
            }
            public void stop() {
                keepRunning.set(false);
            }
            public Consumer getConsumer() {
                return consumer;
            }
            @Override
            protected Void doInBackground() throws Exception {
                while (keepRunning.get()) {
                    String message= getConsumer().next();
                    publish(message);
                }
                return null;
            }
            @Override
            protected void process(List<String> chunks) {
                for (String msg : chunks) {
                    model.addElement(msg);
                }
            }
        }
    }
    

    귀하의 회신과 특히 poll() 대신 take()를 사용하는 팁에 감사드립니다. 하지만 제 문제에 대해 알아냈습니다. 사실 나는 GUI 스레드 내부에서 다른 스레드를 호출하고 있었습니다. 모든 스레드를 분리하고 GUI를 포함한 모든 스레드를 시작하는 또 다른 클래스를 만들면 문제가 해결되고 디스플레이가 업데이트되었습니다.

    WHXY2022-02-08 07:39:12
  • 이전 javascript : 예상 길이의 다차원 배열
  • 다음 microservices : 클라이언트와 서비스 간의 비동기식 통신