有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程Java文件传输程序在执行SwingWorker之前挂起

我编写了一个程序,它使用多播来发现本地网络上的对等点,并允许它们之间进行文件传输。它可以工作,除了一些获取文件/初始化传输线程的过程慢得可笑之外。它挂起约10-15秒,然后开始传输并正常完成:

转移。爪哇

  • 我的jframegui类。为了方便起见,这是用Netbeans完成的,所以任何生成的代码都不会发布在这里

    package transfer;
    
    import java.beans.PropertyChangeEvent;
    import java.io.File;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.JFileChooser;
    import static javax.swing.JFileChooser.FILES_AND_DIRECTORIES;
    import javax.swing.SwingWorker;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Transfer extends javax.swing.JFrame {
    
        private final FileDrop fileDrop;
        private Client client;
        private final Server server;
        private final ClientMulticast clientMulticast;
        private final ServerMulticast serverMulticast;
    
        public Transfer() throws IOException {
            initComponents();
    
            this.setTitle("Transfer");
            peerBox.setEditable(false);
            peerBox.removeAllItems();
    
            fileDrop = new FileDrop(backgroundPanel, (java.io.File[] files) -> {
    
                System.out.println(files[0].isDirectory());
    
                if (peerBox.getSelectedIndex() != -1) {
    
                    sendLabel.setText("Hello");
                    try {
                        client = new Client(sendLabel, files, (Peer) peerBox.getSelectedItem());
    
                        //Client property change listener - listens for updates to progress bar
                        client.addPropertyChangeListener((PropertyChangeEvent evt1) -> {
    
                            if (null != evt1.getPropertyName()) switch (evt1.getPropertyName()) {
                                case "progress":
                                    sendProgressBar.setValue((Integer) evt1.getNewValue());
                                    break;
                            }
                        });
    
                        client.execute();
    
                    } catch (Exception ex) {
                        System.out.println("Unable to send! IOException in FileDrop call.");
                        ex.printStackTrace(System.out);
                    }
    
                } else {
                    sendLabel.setText("Host not found");
                }
            });
    
    
            sendProgressBar.setMaximum(100);
            sendProgressBar.setMinimum(0);
            receiveProgressBar.setMaximum(100);
            receiveProgressBar.setMinimum(0);
    
    
            server = new Server(receiveLabel);
    
            //Server property change listener - listens for updates to progress bar
            server.addPropertyChangeListener((PropertyChangeEvent evt1) -> {
                if ("progress".equals(evt1.getPropertyName())) {
                    receiveProgressBar.setValue((Integer) evt1.getNewValue());
                }
            });
    
            server.execute();
    
            serverMulticast = new ServerMulticast();
            serverMulticast.execute();
            clientMulticast = new ClientMulticast(peerBox);
            clientMulticast.execute();
    
        }
    
        ...GENERATED CODE...
    
        private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
            Transfer guiObject = this;
    
            SwingWorker openFile = new SwingWorker<Void, String>() {
    
                @Override
                protected Void doInBackground() throws Exception {
    
                    openButton.setEnabled(false);
    
                    fileChooser.setFileSelectionMode(FILES_AND_DIRECTORIES);
    
                    int returnVal = fileChooser.showOpenDialog(guiObject);
    
                    if (returnVal == JFileChooser.APPROVE_OPTION && peerBox.getSelectedIndex() != -1) {
    
                    File[] fileArray = fileChooser.getSelectedFiles();                    
    
                    client = new Client(sendLabel, fileArray, (Peer) peerBox.getSelectedItem());
    
                    //Client property change listener - listens for updates to progress bar
                    client.addPropertyChangeListener((PropertyChangeEvent evt1) -> {
                        if ("progress".equals(evt1.getPropertyName())) {
                            sendProgressBar.setValue((Integer) evt1.getNewValue());
                        }
                    });
    
                    client.execute();
    
                    //block this swingworker until client worker is done sending
                    while(!client.isDone()) { }
                }
    
                    openButton.setEnabled(true);
    
                    return null;
                }
            };
    
                openFile.execute();
        }                                          
    
    
        /**
         * @param args the command line arguments
         * @throws java.lang.ClassNotFoundException
         * @throws java.lang.InstantiationException
         * @throws java.lang.IllegalAccessException
         * @throws javax.swing.UnsupportedLookAndFeelException
         */
        public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Transfer");
    
        UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
    
            /* Create and display the form */
            java.awt.EventQueue.invokeLater(() -> {
                try {
                    new Transfer().setVisible(true);
                } catch (IOException ex) {
                Logger.getLogger(Transfer.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
    }
    
        // Variables declaration - do not modify                     
        private javax.swing.JPanel backgroundPanel;
        private javax.swing.JFileChooser fileChooser;
        private javax.swing.JButton openButton;
        private javax.swing.JComboBox<Peer> peerBox;
        private javax.swing.JLabel receiveHeaderLabel;
        private javax.swing.JLabel receiveLabel;
        private javax.swing.JPanel receivePanel;
        private javax.swing.JProgressBar receiveProgressBar;
        private javax.swing.JLabel sendHeaderLabel;
        private javax.swing.JLabel sendLabel;
        private javax.swing.JPanel sendPanel;
        private javax.swing.JProgressBar sendProgressBar;
        // End of variables declaration                   
    }
    

ClientMutlicast。爪哇

  • 发送多播数据包并接收响应-相应地修改GUI。此类是错误所在的位置

    package transfer;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.SocketTimeoutException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    import javax.swing.JComboBox;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    
    public class ClientMulticast extends SwingWorker<Void, Peer> {
    
    private boolean peerPreviouslyFound;
    private byte[] sendData, receiveData;
    private final DatagramSocket mSocket;
    private DatagramPacket receivePacket;
    private final JComboBox<Peer> peerBox;
    private Peer peer;
    private ArrayList<Peer> peerList;
    
        public ClientMulticast(JComboBox<Peer> peerBox) throws SocketException {
    
            peerList = new ArrayList<>();
            this.peerBox = peerBox;
    
            mSocket = new DatagramSocket();
            mSocket.setBroadcast(true);
            mSocket.setSoTimeout(300);
    
            sendData = "CLIENT_MSG".getBytes();
        }
    
            @Override
            protected Void doInBackground() throws IOException, InterruptedException, InvocationTargetException {
                while (true) {
                    try {
                        receiveData = new byte[1024];
                        receivePacket = new DatagramPacket(receiveData, receiveData.length);
    
                        peerPreviouslyFound = false;
    
                        //send broadcast message
                        mSocket.send(new DatagramPacket(sendData, sendData.length, InetAddress.getByName("239.255.255.255"), 8888));
    
                        //receive response
                        mSocket.receive(receivePacket);
    
                        //don't have to worry about responses from local host because
                        //server rejects multicast packets from local host
                        peer = new Peer(receivePacket.getAddress(), receivePacket.getPort(),                         System.currentTimeMillis());
    
                    for (Peer peerList1 : peerList) {
                        if (peerList1.getIPAddress().equals(peer.getIPAddress())) {
                            peerList1.setTimestamp(System.currentTimeMillis());
                            peerPreviouslyFound = true;
                            break;
                        }
                    }
    
                    //add to peer list only if reponse is valid, not from local host, and not previously received from this host
                    if ("SERVER_RESPONSE".equalsIgnoreCase(new String(receivePacket.getData()).trim())
                    && !peerPreviouslyFound) {
    
                        //publish(peer);
                        peerBox.addItem(peer);
                        peerList.add(peer);
                    }
    
                    for (int i = 0; i < peerList.size(); i++) {
                        //if peer is greater than 5 seconds old, remove from list
                        if (peerList.get(i).getTimestamp() + 5000 < System.currentTimeMillis()) {
                            peerBox.removeItemAt(i);
                            peerList.remove(i);
                        }
                    }
                } catch (SocketTimeoutException ex) {
                    for (int i = 0; i < peerList.size(); i++) {
                        //if peer is greater than 5 seconds old, remove from list
                        if (peerList.get(i).getTimestamp() + 5000 < System.currentTimeMillis()) {
                            final int j = i;
    
                            SwingUtilities.invokeAndWait(() -> {
                                peerBox.removeItemAt(j);
                                peerList.remove(j);
                            });
    
                        }
                    }
                }
    
                TimeUnit.MILLISECONDS.sleep(500);
            }//end while
        }
    
        @Override
        protected void process(List<Peer> p) {
            peerBox.addItem(p.get(p.size() - 1));
            peerList.add(p.get(p.size() - 1));
        }
    
    }
    

我很确定问题在于UI构造函数中的FileDrop对象试图使用客户端执行客户端SwingWorker。execute(),有很大的延迟。我可以调试它,但它没有显示任何问题。另外,我知道问题不可能出在我的插座上。在Client()内调用connect(),因为print语句紧跟在socket之前。connect()在程序从挂起的任何位置恢复之前不会打印。有什么想法吗?我完全迷路了

--编辑:上面的所有代码都可以正常工作,这里提到的错误已经解决。如果有人想要完整的资料来源,我很乐意与大家分享


共 (1) 个答案

  1. # 1 楼答案

    我正在将名为peerBox的组合框传递给我的ClientMuticast类。我直接修改了这个结构,在其中存储对等点。这阻塞了接口线程,因为ClientMulticast类一直在访问/更改组合框
    我更改了代码,使用组合框仅向gui显示值并存储发现的对等点。数组列表用于在每次调用ClientMulticast构造函数时复制组合框中的所有值。如果发现对等体,则通过ClientMulticast类中的publish()process()方法更新组合框。放置在process()内的任何代码都将计划在EDT上执行