我正在创建4个线程,每个线程都与UI相关联。 UI执行长时间运行的任务,因为我使用了SwingWorker。 但是出现的问题不是作为多线程应用程序运行,而是在队列中运行。
有趣的是,当我删除SwingWorker时,它的行为和运行方式都是多线程的。
我的代码如下:
的NewClass
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();
}
}
}
UI类
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中的工作线程的替代方法是什么?
答案 0 :(得分:3)
嗯,不,这不是多线程在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;
}
}
}
}