gpt4 book ai didi

java - 多线程 Jframes 中的 SwingWorker

转载 作者:行者123 更新时间:2023-11-30 07:11:55 26 4
gpt4 key购买 nike

我正在创建 4 个线程,每个线程都与一个 UI 相关联。UI 执行长时间运行的任务,为此我使用了 SwingWorker。但是出现的问题是它不是作为多线程应用程序运行,而是在队列中运行。

有趣的是,当我删除 SwingWorker 时,它会以多线程方式运行。

我的代码如下:

新类

package thread;

public class NewClass
{
public static void main(String[] args) throws Exception
{
for(int i=0; i<4 ; i++)
{
new ThreadFront().startsThread();
Thread.sleep(2000);
}
}
}

class ThreadFront implements Runnable
{
private Thread t;

public ThreadFront()
{
t = new Thread(this, "");

}

public void startsThread()
{
t.start();
}

@Override
public void run()
{
try
{
UI ui = new UI();
ui.startThread();
}
catch(Exception ae)
{
ae.printStackTrace();
}
}
}

界面类

package thread;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingWorker;

public class UI extends javax.swing.JFrame
{
public UI()
{
initComponents();
setVisible(true);
}

public void startThread() throws Exception
{
new SwingWorker<Integer, Integer>()
{
@Override
protected Integer doInBackground() throws Exception
{
for(int i=0; i<10;i++)
{
jTextArea1.append(""+i);
Thread.sleep(3000);
}
return 0;
}

@Override
protected void process(List<Integer> chunks)
{
for(Integer message : chunks)
{
jProgressBar1.setValue(message);
jProgressBar1.repaint();
}
}

@Override
protected void done()
{
try
{
get();
}
catch(final Exception ex)
{
ex.printStackTrace();
}
}
}.execute();
}

// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

jPanel1 = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
jPanel3 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
jLabel2 = new javax.swing.JLabel();
jobid_field = new javax.swing.JLabel();
jProgressBar1 = new javax.swing.JProgressBar();
work_field = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
session_field = new javax.swing.JLabel();

setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setLocationByPlatform(true);
setResizable(false);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
formWindowClosing(evt);
}
});

jPanel1.setLayout(new java.awt.BorderLayout());

jPanel2.setBackground(new java.awt.Color(204, 204, 204));
jPanel2.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(255, 255, 255)));
jPanel2.setForeground(new java.awt.Color(204, 204, 204));

jLabel1.setFont(new java.awt.Font("Century Gothic", 1, 14)); // NOI18N
jLabel1.setText("iZoneX Math Process");

javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 304, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(86, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);

jPanel1.add(jPanel2, java.awt.BorderLayout.NORTH);

jPanel3.setBackground(new java.awt.Color(204, 204, 204));
jPanel3.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(255, 255, 255)));

jTextArea1.setEditable(false);
jTextArea1.setBackground(new java.awt.Color(255, 255, 204));
jTextArea1.setColumns(20);
jTextArea1.setFont(new java.awt.Font("Century Gothic", 1, 12)); // NOI18N
jTextArea1.setForeground(new java.awt.Color(255, 0, 0));
jTextArea1.setLineWrap(true);
jTextArea1.setRows(5);
jTextArea1.setWrapStyleWord(true);
jScrollPane1.setViewportView(jTextArea1);

jLabel2.setText("Job ID. :");

jLabel4.setText("Processing: ");

jLabel3.setText("Session ID: ");

javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel3Layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jobid_field, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(33, 33, 33)
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(session_field, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(jProgressBar1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel3Layout.createSequentialGroup()
.addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(work_field, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jobid_field, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel3)
.addComponent(session_field, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 148, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(work_field, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);

jPanel1.add(jPanel3, java.awt.BorderLayout.CENTER);

getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

pack();
}// </editor-fold>

private void formWindowClosing(java.awt.event.WindowEvent evt) {

}

// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JProgressBar jProgressBar1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JLabel jobid_field;
private javax.swing.JLabel session_field;
private javax.swing.JLabel work_field;
// End of variables declaration

}

在这种情况下,Swing 中工作线程的替代方案是什么?

最佳答案

嗯,不,这不是多线程在 Swing 中的工作方式。

只有一个 UI 线程(称为事件调度线程),所有更新和与 UI 的交互都应在 EDT 的上下文中完成,因此执行诸如...

@Override
public void run()
{
try
{
UI ui = new UI();
ui.startThread();
}
catch(Exception ae)
{
ae.printStackTrace();
}
}

还有……

@Override
protected Integer doInBackground() throws Exception
{
for(int i=0; i<10;i++)
{
jTextArea1.append(""+i);
Thread.sleep(3000);
}
return 0;
}

实际上是在违反这个规则。

相反,每个 UI 都应该有自己的 SwingWorker(就像现在一样),但应该在 EDT 的上下文中创建。

每个 SwingWorker 都应该调用 publish 以便将 doInBackground 方法的结果推送回 EDT。

SwingWorker 通过 PropertyChange 支持有自己的进度支持

例如……

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MultiThreadedUI {

public static void main(String[] args) {
new MultiThreadedUI();
}

public MultiThreadedUI() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

final List<TestPane> panes = new ArrayList<>(5);
for (int index = 0; index < 5; index++) {
panes.add(new TestPane(Integer.toString(index)));
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 1));
for (TestPane pane : panes) {
frame.add(pane);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (TestPane pane : panes) {
pane.makeItSo();
}
}
});
}
});
}

public class TestPane extends JPanel {

private JTextArea textArea;
private JProgressBar pb;
private String name;

public TestPane(String name) {
this.name = name;
textArea = new JTextArea(10, 5);
pb = new JProgressBar();
setLayout(new BorderLayout());
add(new JScrollPane(textArea));
add(pb, BorderLayout.SOUTH);
}

public void makeItSo() {

BackgroundWorker worker = new BackgroundWorker();
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
pb.setValue((Integer)evt.getNewValue());
}
}
});
worker.execute();

}

protected class BackgroundWorker extends SwingWorker<Integer, Integer> {

@Override
protected void process(List<Integer> chunks) {
for (Integer value : chunks) {
textArea.append(name + ": " + value + "\n");
}
}

@Override
protected Integer doInBackground() throws Exception {
int delay = (int)(Math.random() * 3000);
for (int i = 0; i < 10; i++) {
publish(i);
setProgress((int) (Math.round(((double) i / (double) 9) * 100)));
Thread.sleep(delay);
}
return 0;
}

}

}

}

关于java - 多线程 Jframes 中的 SwingWorker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20739488/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com