多线程Jframe中的SwingWorker [英] SwingWorker In multithreaded Jframes
问题描述
我正在创建4个线程,每个线程都与一个UI关联. UI执行了长期运行的任务,为此,我使用了SwingWorker. 但是出现的问题是它不是在多线程应用程序中运行,而是在队列中运行.
I am creating 4 threads and each thread is associated with a UI. The UI performs a long running task, for that I have used a SwingWorker. But the problem that arises is instead of running as a multithreaded app, it is running in queue.
有趣的是,当我删除SwingWorker时,它的行为和运行都是多线程的.
Interesting to note that when I remove the SwingWorker it behaves and runs as multithreaded.
我的代码是:
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中辅助线程的替代方案是什么?
What would be the alternative to worker Threads in Swing in that case?
推荐答案
嗯,不,这不是Swing中多线程的工作原理.
Um, no, this is not how multithreading works in Swing.
只有一个UI线程(称为事件调度线程),所有更新和与UI的交互都应在EDT的上下文内完成,因此可以执行...
There is a single UI thread (known as the Event Dispatching Thread), all updates and interactions with the UI are expected to be done from within the context of the EDT, so doing things like...
@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;
}
实际上违反了这一规则.
Are actually breaking this rule.
相反,每个UI
应该具有自己的SwingWorker
(现在是这样),但是应该在EDT的上下文中创建.
Instead, each UI
should have its own SwingWorker
(as it does now), but should be created from within the context of the EDT.
每个SwingWorker
应该正在调用publish
,以便将doInBackground
方法的结果推回EDT.
Each SwingWorker
should be calling publish
in order to push the results of the doInBackground
method back to the EDT.
SwingWorker
通过PropertyChange
支持具有自己的进度支持
SwingWorker
has its own progress support via the PropertyChange
support
例如...
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;
}
}
}
}
这篇关于多线程Jframe中的SwingWorker的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!