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