我正在尝试编写使用线程的Java UI应用程序。线程1更新进度条,而线程2将字符串写入文件。但是,每当我尝试将它们组合在一起时,其中一个就无法工作。进度条会更新,但打印到文件失败或打印到文件成功,而进度条没有更新。有趣的是,如果我尝试System.out.println而不是buffer.append()。它工作正常。帮助我,伙计们
class updating implements Runnable {
JProgressBar j;
writing writing;
updating(writing writing, JProgressBar j) {
this.writing = writing;
this.j = j;
}
@Override
public void run() {
while (true) {
String message = writing.getMessage();
Matcher matcher = Pattern.compile("\\d+").matcher(message);
matcher.find();
int i = Integer.valueOf(matcher.group());
j.setValue(i);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(updating.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class writing implements Runnable{
int i;
BufferedWriter bw;
writing(BufferedWriter bw, int i) {
this.i = i;
this.bw = bw;
}
private List messages = new ArrayList();
private List messages1 = new ArrayList();
@Override
public void run() {
while (true && i<=100) {
putMessage(i);
i++;
System.out.println(getMessage1());
}
}
public synchronized void putMessage(int i) {
while (messages.size() >= 0x5) {
try {
wait();
} catch (InterruptedException e) {
}
}
messages.add("Printing: " + i + "\r\n");
notify();
}
public synchronized String getMessage() {
while (messages.isEmpty()) {
try {
notify();
wait();
} catch (Exception e) {
}
}
String message = (String) messages.remove(0);
notify();
messages1.add(message);
return message;
}
public synchronized String getMessage1() {
while (messages1.isEmpty()) {
try {
notify();
wait();
} catch (Exception e) {
}
}
String message = (String) messages1.remove(0);
notify();
return message;
}
public boolean checking(){
return messages.isEmpty();
}
}
//UI
public class wThread extends javax.swing.JFrame {
/** Creates new form wThread */
public wThread() {
initComponents();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
jProgressBar1 = new javax.swing.JProgressBar();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setText("Status");
jButton1.setText("Cancel");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jButton2.setText("Start");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(65, 65, 65)
.addComponent(jButton2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 68, Short.MAX_VALUE)
.addComponent(jLabel1)
.addGap(179, 179, 179))
.addGroup(layout.createSequentialGroup()
.addContainerGap(132, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(122, 122, 122))
.addGroup(layout.createSequentialGroup()
.addComponent(jButton1)
.addGap(157, 157, 157))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(49, 49, 49)
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jButton1))
.addGroup(layout.createSequentialGroup()
.addGap(32, 32, 32)
.addComponent(jButton2)))
.addContainerGap(166, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
System.exit(0);
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
File f = new File("D:\\log.txt");
BufferedWriter bf = null;
try {
bf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
} catch (FileNotFoundException ex) {
Logger.getLogger(wThread.class.getName()).log(Level.SEVERE, null, ex);
}
jProgressBar1.setStringPainted(true);
int i = 0;
writing writer = new writing(bf, i);
new Thread(writer).start();
updating updater = new updating(writer, jProgressBar1);
new Thread(updater).start();
try {
if(writer.checking()){
bf.close();
}
} catch (IOException ex) {
Logger.getLogger(wThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new wThread().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JProgressBar jProgressBar1;
// End of variables declaration
}
答案 0 :(得分:0)
您只能从SwingThread触摸UI组件。从来没有任何其他线程。好消息是你需要一个单独的线程来完成Swing Thread的工作才能使它工作(比你当前的架构更少的资源)。这大致是你做的:
public void doLongRunningThing() {
final JProgressBar bar = ....; // this comes from somewhere, maybe you create it or look it up.
Thread workerThread = new Thread( new Runnable() {
public void run() {
try {
for( int i = 0; i < words.length; i++ ) {
doSomeWorkOn( words[i] );
final int progress = i; // have to handle Java-ism
SwingUtilities.invokeLater( new Runnable() {
public void run() {
bar.setProgress( progress );
}
});
}
} finally {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
// todo clean up the UI like hide the dialog or hide progress bar, etc.
}
});
}
}
} );
worker.start();
}
SwingUtilities.invokeLater()将一个runnable排队,以便从另一个线程在SwingThread上运行。因此,触摸排队的runnable中的swing组件是安全的。我会考虑使用ExecutorService而不是原始线程它实际上只会将线程实例化更改为:
// create a thread pool out in your program for background jobs
// then share that for all areas where you are doing background work,
// network calls, etc.
ExecutorService executor = Executors.newFixedThreadPool(5);
public void doLongRunningThing() {
final JProgressBar bar = ....; // this comes from somewhere, maybe you create it or look it up.
executor.execute( new Runnable() {
public void run() {
...same code as above...
}
} );
}