|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
[Java] Due SwingWorker contemporanei nello stesso metodo? Non vanno
Salve,
Oggi mentre provavo a giocherellare con SwingWorker e sperimentare il multithreading con Swing, ho steso queste righe di codice nel costruttore di un JPanel: Codice:
SwingWorker sw1 = new SwingWorker<Void, Void>()
{
@Override
public Void doInBackground()
{
while(true)
{
clock.setText(Long.toString(System.currentTimeMillis()));
try
{
Thread.sleep(25);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
};
SwingWorker sw2 = new SwingWorker<Void, Void>()
{
@Override
public Void doInBackground()
{
while(true)
{
clocc.setText(Long.toString(System.currentTimeMillis()));
try
{
Thread.sleep(250);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
};
sw1.execute();
sw2.execute();
Se commento la penultima riga sw1.execute() invece, la JLabel clocc viene modificata come previsto. Che cosa succede? E` possibile far partire in background due SwingWorker contemporaneamente dallo stesso metodo? (In questo caso un costruttore, il codice e` stato omesso qui) Mi aspettavo di si`, ma invece... O c'e` qualcosa che sbaglio? Mi aspettavo che gli SwingWorker fossero un'alternativa comoda built-in al creare un EventQueue.invokeLater in un oggetto Runnable incapsulato in un un Thread.
__________________
~
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Veramente a me così funziona:
Codice:
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
/**
*
* @author francesco
*/
public class DoubleSwingworker extends JPanel
{
public static void main(String[] args) {
JFrame frame = new JFrame("Double SwingWorker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DoubleSwingworker dsw = new DoubleSwingworker();
frame.add(dsw);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JLabel clock, clocc;
public DoubleSwingworker() {
super(new GridLayout(1, 2, 20, 0));
clock = new JLabel("clock");
clocc = new JLabel("clocc");
add(clock);
add(clocc);
SwingWorker sw1 = new SwingWorker<Void, Void>() {
@Override public Void doInBackground() {
while(true) {
clock.setText(Long.toString(System.currentTimeMillis()));
try { Thread.sleep(25);
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}
};
SwingWorker sw2 = new SwingWorker<Void, Void>() {
@Override public Void doInBackground() {
while(true) {
clocc.setText(Long.toString(System.currentTimeMillis()));
try { Thread.sleep(250);
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}
};
sw1.execute();
sw2.execute();
}
}
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 05-05-2010 alle 22:02. |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Mi da' lo stesso problema che ho con il mio codice:
![]() In teoria le due JLabel dovrebbero ad intervalli diversi riportare l'orario del sistema in millisecondi.
__________________
~
Ultima modifica di s12a : 05-05-2010 alle 22:11. |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Ah, beh, non saprei
Vediamo un po', prova a darci questi dati: Versione del JDK? della JVM? Su che SO?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Credevo di starmi rincretinendo, invece c'e` davvero qualcosa di strano allora!
Quote:
Ho installate sia la versione a 32 che a 64 bit. (Come IDE uso Eclipse per Windows, il quale e` solo a 32 bit e funziona solo abbinandogli da riga di comando la JVM a 32 bit) OS: Windows 7 64 bit con tutti gli ultimi aggiornamenti installati.
__________________
~
|
|
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Non noto niente di strano. Più che altro volevo controllare la versione del JDK, francamente.
Comunque io sono su SO WindowsXP, e come ide NetBeans. La JDK è la 1.6.0_05. Prova questo codice (i due SwingWorker vengono mandati in esecuzione solo quando viene aperta la finestra, non più nel costruttore): Codice:
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
/**
*
* @author francesco
*/
public class DoubleSwingworker extends JPanel
{
public static void main(String[] args) {
JFrame frame = new JFrame("Double SwingWorker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DoubleSwingworker dsw = new DoubleSwingworker();
frame.add(dsw);
frame.addWindowListener(dsw.getListener());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JLabel clock, clocc;
private WindowListener listener;
public DoubleSwingworker() {
super(new GridLayout(1, 2, 20, 0));
clock = new JLabel("clock clock clock");
clocc = new JLabel("clocc clocc clocc");
add(clock);
add(clocc);
final SwingWorker sw1 = new ClockCounter(clock, 25);
final SwingWorker sw2 = new ClockCounter(clocc, 250);
listener = new WindowAdapter() {
@Override public void windowOpened(WindowEvent e) {
sw1.execute();
sw2.execute();
}
};
}
public WindowListener getListener() {
return listener;
}
class ClockCounter extends SwingWorker<Void, Void>
{
final JLabel CLOCK;
final long MILLIS;
public ClockCounter(JLabel lab, long millis) {
CLOCK = lab;
MILLIS = millis;
}
@Override
public Void doInBackground() {
while (true) {
CLOCK.setText(Long.toString(System.currentTimeMillis()));
try {
Thread.sleep(MILLIS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Idem:
![]() Mi chiedo se magari gli ultimi update abbiano introdotto qualche bug o regressione... ma ad occhio mi sembra qualcosa di troppo grosso per passare inosservato.
__________________
~
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Sembra quasi che da te l'implementazione di SwingWorker usi un thread unico come worker thread...
Aggiungi queste due righe al metodo doInBackground, subito prima del while: Codice:
System.out.println("Worker Thread launched:");
System.out.println(Thread.currentThread().getName());
Quote:
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Si`, hai ragione. Questo e` quello che stampa a me.
Il secondo thread non parte: Quote:
__________________
~
Ultima modifica di s12a : 05-05-2010 alle 22:53. |
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Estratto dai sorgenti del mio JDK (metodo execute di SwingWorker):
Quote:
Se vuoi avere confrema al 100% prova a eseguire un ciclo che termina dopo un po' nel doInBackground: finita l'esecuzione del primo SwingWorker dovresti notare la partenza del secondo...
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Sorpresa!
E' un bug di SwingWorker. http://bugs.sun.com/view_bug.do?bug_id=6880336 in pratica dalla 1.6._17 fino alla 20 "execute" è bloccante. Puoi aggirare il problema con: ExecutorService pool = Executors.newFixedThreadPool(2); pool.submit(sw1); pool.submit(sw2); pool.shutdown(); Ps.: il "setText" va messo nel metodo process di SwingWorker, non nel doInBackground.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! Ultima modifica di PGI-Bis : 05-05-2010 alle 23:01. |
|
|
|
|
|
#12 | ||||
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Quote:
Quote:
Quote:
Vedro` di tenere conto della soluzione. Quote:
__________________
~
Ultima modifica di s12a : 05-05-2010 alle 23:05. |
||||
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
PGI, se non ci fossi, bisognerebbe inventarti!
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Quote:
Lo SwingWorker qui da' problemi nel metodo process. @Override non da' nemmeno come corretto l'overloading del metodo: Codice:
SwingWorker<Void, Void> sw1 = new SwingWorker<Void, Void>() {
@Override public Void doInBackground() { return null; }
@Override protected void process(Void x) {
while(true) {
try {
clock.setText(Long.toString(System.currentTimeMillis()));
Thread.sleep(25);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
};
Thread t2 = new Thread(new Runnable() {
@Override public void run() {
while(true) {
try {
SwingUtilities.invokeLater(updater);
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
});
sw1.execute();
t2.start();
__________________
~
Ultima modifica di s12a : 06-05-2010 alle 12:17. |
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Per il tipo di compito che esegue il tuo esempio è più comodo javax.swing.Timer.
Codice:
Timer timer = new Timer(periodo, new ActionListener() {
public void actionPerformed(ActionEvent e) {
aggiorna etichetta
}
});
timer.start();
Codice:
new SwingWorker<Void, Void>() {
protected Void doInBackground() throws Exception {
while(true) {
Thread.sleep(25);
publish();
}
}
protected void process(List<Void> chunks) {
etichetta.setText(System.currentTimeMillis());
}
}.execute();
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#16 | ||
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Quote:
Quote:
Ecco i tre modi che ho avuto modo di provare per fare la stessa identica cosa: Codice:
SwingWorker<Void, Void> sw1 = new SwingWorker<Void, Void>() {
@Override public Void doInBackground() {
while(true) {
try {
Thread.sleep(25);
publish();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
@Override protected void process(List<Void> chunks) {
clock.setText(Long.toString(System.currentTimeMillis()));
}
};
Thread th2 = new Thread(new Runnable() {
private Runnable updater = new Runnable() {
@Override public void run() {
clocc.setText(Long.toString(System.currentTimeMillis()));
}
};
@Override public void run() {
while(true) {
try {
SwingUtilities.invokeLater(updater);
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
});
Timer tm3 = new Timer(350, new ActionListener() {
@Override public void actionPerformed(ActionEvent arg0) {
clokk.setText(Long.toString(System.currentTimeMillis()));
}
});
sw1.execute();
th2.start();
tm3.start();
__________________
~
Ultima modifica di s12a : 06-05-2010 alle 14:30. |
||
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Curiosità mia: nel caso si usi SwingWorker, ma è proprio neccessario far eseguire una setText (che è uno dei pochi metodi di Swing ad essere thread-safe) nel metodo process, invece che in doInBackground?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Direi che il setText a cui fai riferimento sia quello di JTextComponent.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
#19 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Jan 2008
Messaggi: 11159
|
Non c'entra piu` molto con lo scopo iniziale del thread, ma visto che ci siamo mi chiedevo solo se in merito a questa applicazione un po' piu` pratica di uno SwingWorker (sempre comunque di prova/a scopi didattici) fosse possibile eliminare il return null evidenziato. Per qualche motivo qui mi viene richiesto. Nella prova precedente di qualche post fa l'ho omesso e non ho avuto problemi:
Codice:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import net.miginfocom.swing.MigLayout;
public class ProgressPanel extends JPanel {
ProgressPanel() {
setLayout(new MigLayout("wrap 1"));
progress.setMinimum(0);
progress.setMaximum(100);
add(statusLabel, "align center");
add(progress, "grow");
add(startButton, "grow");
startButton.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
startButton.setEnabled(false);
new SwingWorker<Void, Void>() {
@Override public Void doInBackground() {
statusLabel.setText("Status: working");
while(progress.getValue() < 100) {
try {
Thread.sleep(rand.nextInt(30));
publish();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Worker thread " + Thread.currentThread().getName() + " abnormally interrupted");
}
}
statusLabel.setText("Status: done!");
startButton.setEnabled(true);
startButton.setText("Quit");
startButton.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
System.exit(0); // Temporary implementation
}
});
return null; // ???
}
@Override protected void process(List<Void> chunks) {
progress.setValue(progress.getValue() + 1);
}
}.execute();
}
});
}
private JProgressBar progress = new JProgressBar();
private JButton startButton = new JButton("Start processing");
private JLabel statusLabel = new JLabel("Status: idling");
private Random rand = new Random();
public static void main(String[] args) {
if (args.length > 0) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.out.println ("Unable to set the platform Look&Feel");
}
}
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
JFrame frame = new JFrame("Saving file");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(new ProgressPanel());
frame.pack();
}
});
}
}
__________________
~
Ultima modifica di s12a : 06-05-2010 alle 17:37. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 02:16.






















