Java 使用SwingWorker在jTable中动态加载大数据

Java 使用SwingWorker在jTable中动态加载大数据,java,swing,file-io,jtable,swingworker,Java,Swing,File Io,Jtable,Swingworker,在Netbeans中,我尝试创建一个桌面应用程序,其UI如下所示: 我正在通过Java代码执行“adb logcat命令”,该代码在几秒钟内加载1000行日志&我打算通过NetBeans中的jTable显示所有这些信息 使用参数:adb logcat-t 100->我现在仅将日志限制为100行。 但是,小程序在1000行内或在取消对行数的限制时会变得无响应(或卡在process()方法中) 我不确定我是否在代码中正确实现了SwingWorker线程。我正在寻找关于如何改进代码的建议,以便在小程

在Netbeans中,我尝试创建一个桌面应用程序,其UI如下所示:

我正在通过Java代码执行“adb logcat命令”,该代码在几秒钟内加载1000行日志&我打算通过NetBeans中的jTable显示所有这些信息

使用参数:adb logcat-t 100->我现在仅将日志限制为100行。 但是,小程序在1000行内或在取消对行数的限制时会变得无响应(或卡在process()方法中)

我不确定我是否在代码中正确实现了SwingWorker线程。我正在寻找关于如何改进代码的建议,以便在小程序没有响应的情况下动态加载大量数据

以下是小程序的实现代码。。。具有两个功能:

  • 从小程序的init()方法调用viewLogs()
  • SwingWorker实现

        public void viewLogs() throws IOException {
    
        String[] command = {"CMD","/C", "adb logcat -t 100"};
        ProcessBuilder probuilder = new ProcessBuilder( command );
        probuilder.directory(new File("c:\\Users\\k.garg\\Desktop\\"));
        Process process = probuilder.start();
    
        InputStream is = process.getInputStream();      
        InputStreamReader isr = new InputStreamReader(is);
        br = new BufferedReader(isr);
    
        DefaultTableModel model = (DefaultTableModel)jTable1.getModel();
        worker.execute();
    
        try {
            int exitVal = process.waitFor();
            System.out.println("exitVal = " + exitVal);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public class TableSwingWorker extends SwingWorker<DefaultTableModel, Object[]>{
    private DefaultTableModel tableModel;
    public TableSwingWorker(DefaultTableModel tableModel){
        this.tableModel = tableModel;
    }
    
    @Override
    protected DefaultTableModel doInBackground() throws Exception {
        Thread.sleep(2000); //added for initial UI to load
        System.out.println("Start populating");
        String line, date, time, loglevel, PID, TID, tag, message="";
        String log;
        int count = 0;
        while ((log = br.readLine()) != null) {
            count++;
    
            String[] splitLog = log.trim().split("\\s+");
            line = Integer.toString(count);
            date = splitLog[0];
            time = splitLog[1];
            PID = splitLog[2];
            TID = splitLog[3];
            loglevel = splitLog[4];
            tag = splitLog[5];
            for(int i=6; i<splitLog.length;i++){
                message += splitLog[i];
            }
            publish(new Object[]{line, date, time, PID, TID, loglevel, tag, message});
        }
        return tableModel;
    }
    
    @Override
    protected void process(List<Object[]> chunks) {
        System.out.println("Adding " + chunks.size() + " rows");
        for(Object[] row: chunks)
            tableModel.insertRow(0,row);
    }
    
    public void viewLogs()引发IOException{
    字符串[]命令={“CMD”、“/C”、“adb logcat-t 100”};
    ProcessBuilder probuilder=新建ProcessBuilder(命令);
    probuilder.directory(新文件(“c:\\Users\\k.garg\\Desktop\”);
    Process=probuilder.start();
    InputStream=process.getInputStream();
    InputStreamReader isr=新的InputStreamReader(is);
    br=新的缓冲读取器(isr);
    DefaultTableModel=(DefaultTableModel)jTable1.getModel();
    worker.execute();
    试一试{
    int exitVal=process.waitFor();
    System.out.println(“exitVal=“+exitVal”);
    }捕捉(中断异常e){
    e、 printStackTrace();
    }
    }
    公共类TableSwingWorker扩展了SwingWorker{
    私有DefaultTableModel表模型;
    公共表WingWorker(DefaultTableModel表模型){
    this.tableModel=tableModel;
    }
    @凌驾
    受保护的DefaultTableModel doInBackground()引发异常{
    Thread.sleep(2000);//为要加载的初始UI添加
    System.out.println(“开始填充”);
    字符串行、日期、时间、日志级别、PID、TID、标记、消息=”;
    字符串日志;
    整数计数=0;
    而((log=br.readLine())!=null){
    计数++;
    字符串[]splitLog=log.trim().split(\\s+);
    行=整数。toString(计数);
    日期=拆分日志[0];
    时间=拆分日志[1];
    PID=splitLog[2];
    TID=拆分日志[3];
    loglevel=splitLog[4];
    tag=splitLog[5];
    对于(inti=6;i而言,关键问题是

    try {
        int exitVal = process.waitFor();
        System.out.println("exitVal = " + exitVal);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    这会阻塞事件调度线程,在
    进程完成之前阻止任何可能的更新,这有点违背了使用
    SwingWorker
    的目的

    您最好直接在
    SwingWorker
    中执行
    过程,比如

    public class TableSwingWorker extends SwingWorker<Integer, Object[]> {
    
        private DefaultTableModel tableModel;
        private int count;
    
        public TableSwingWorker(DefaultTableModel tableModel) {
            this.tableModel = tableModel;
        }
    
        @Override
        protected Integer doInBackground() throws Exception {
            count = 0;
            
            String[] command = {"CMD", "/C", "adb logcat -t 100"};
            ProcessBuilder probuilder = new ProcessBuilder(command);
            probuilder.directory(new File("c:\\Users\\k.garg\\Desktop\\"));
            Process process = probuilder.start();
    
            InputConsumer consumer = new InputConsumer(process.getInputStream());
            consumer.start();
            
            int result = process.waitFor();
            consumer.join();
    
            return result;
        }
    
        @Override
        protected void process(List<Object[]> chunks) {
            System.out.println("Adding " + chunks.size() + " rows");
            for (Object[] row : chunks) {
                tableModel.insertRow(0, row);
            }
        }
        
        protected void processOutput(String text) {
                count++;
    
                String[] splitLog = text.trim().split("\\s+");
                String line = Integer.toString(count);
                String date = splitLog[0];
                String time = splitLog[1];
                String PID = splitLog[2];
                String TID = splitLog[3];
                String loglevel = splitLog[4];
                String tag = splitLog[5];
                
                StringBuilder message = new StringBuilder(64);
                for (int i = 6; i < splitLog.length; i++) {
                    message.append(splitLog[i]);
                }
                publish(new Object[]{line, date, time, PID, TID, loglevel, tag, message});
        }
    
        public class InputConsumer extends Thread {
    
            private InputStream is;
    
            public InputConsumer(InputStream is) {
                this.is = is;
                start();
            }
    
            @Override
            public void run() {
                try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
                    String text = null;
                    while ((text = br.readLine()) != null) {
                        processOutput(text);
                    }
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        }
    }
    
    公共类TableSwingWorker扩展SwingWorker{
    私有DefaultTableModel表模型;
    私人整数计数;
    公共表WingWorker(DefaultTableModel表模型){
    this.tableModel=tableModel;
    }
    @凌驾
    受保护的整数doInBackground()引发异常{
    计数=0;
    字符串[]命令={“CMD”、“/C”、“adb logcat-t 100”};
    ProcessBuilder probuilder=新建ProcessBuilder(命令);
    probuilder.directory(新文件(“c:\\Users\\k.garg\\Desktop\”);
    Process=probuilder.start();
    InputConsumer=新的InputConsumer(process.getInputStream());
    consumer.start();
    int result=process.waitFor();
    consumer.join();
    返回结果;
    }
    @凌驾
    受保护的无效进程(列表块){
    System.out.println(“添加”+chunks.size()+“行”);
    对于(对象[]行:块){
    tableModel.insertRow(0,行);
    }
    }
    受保护的void processOutput(字符串文本){
    计数++;
    字符串[]splitLog=text.trim().split(\\s+);
    字符串行=整数.toString(计数);
    字符串日期=拆分日志[0];
    字符串时间=拆分日志[1];
    字符串PID=splitLog[2];
    字符串TID=splitLog[3];
    字符串loglevel=splitLog[4];
    String tag=splitLog[5];
    StringBuilder消息=新的StringBuilder(64);
    对于(int i=6;i
    好吧,这看起来有点“沉重”,但它有两个重要的作用:

  • 它将进程的
    输入流的读取卸载到另一个
    线程
    ,这允许我们
  • waitFor
    要退出的进程,这样我们就可以得到退出值,这有助于诊断某些东西为什么不工作
  • 其他意见
    • Applet的本质是在严格的安全约束下运行的,这通常意味着它们不允许在其他机器上执行程序
    • 小程序也不再受支持。有关详细信息,请参阅和
      • 关键问题是

        try {
            int exitVal = process.waitFor();
            System.out.println("exitVal = " + exitVal);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        这会阻塞事件调度线程,在
        进程完成之前阻止任何可能的更新,这有点违背了使用
        SwingWorker
        的目的

        <