задание 21.10 - таймеры и многопоточность
|
|
CHerry | Дата: Суббота, 2011-10-22, 16:37:34 | Сообщение # 1 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| Реализовать на swing два потока таймеров.
статья про потоки и swing
|
|
| |
CHerry | Дата: Суббота, 2011-10-22, 16:37:44 | Сообщение # 2 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| Мой рабочий пример с потоками, но пока в консоли... кстати в Java 1.5 был добавлен новый пакет java.util.concurrent, который более гибко реализует многопоточность и позволяет реализовать параллельные вычисления.
Создаем наш главный класс Timers откуда и будут стартовать потоки запуска других таймеров Code import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
public class Timers { /** * @author Cherry * Реализация многопоточности с использованием исполнителей (executors) * из библиотеки java.util.concurent * этот способ запуска рекомендован для использования начиная с версии Java SE5 */ public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); System.out.println("создаем первый поток"); exec.execute(new MyTimer()); System.out.println("создаем второй поток"); exec.execute(new MyTimer()); System.out.println("создаем третий поток"); exec.execute(new MyTimer()); }
}
далее создаем MyTimer класс (в нашем проекте), который будет реализовывать работу наших таймеров, экземпляров класса MyTimer. Code // наш класс обязательно должен реализовать интерфейс Runnable // который включает в себя метод run()
public class MyTimer implements Runnable{ // счетчик и ключ для определения номера экземпляра класса (потока) static int count=1; final int id = count++; MyTimer() { System.out.println("номер потока id="+id); } public void run() { for (int i=1;i<10;i++){ System.out.print(" #"+id); try { Thread.sleep(100); } catch (InterruptedException e) {} } } }
|
|
| |
CHerry | Дата: Воскресенье, 2011-10-23, 00:05:12 | Сообщение # 3 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| А вот в swing ничего не получается. А точнее вроде как поток создается, но вывести не удается.
Code package ua.at.javac; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
import javax.swing.SwingUtilities;
public class TimerJFrame extends javax.swing.JFrame{
private javax.swing.JButton jButtonStart; private static javax.swing.JLabel jLabelTimer1; private javax.swing.JLabel jLabelTimer2; private static final long serialVersionUID = 1L;
public javax.swing.JLabel getjLabelTimer1() { return jLabelTimer1; }
public void setjLabelTimer1(javax.swing.JLabel jLabelTimer1) { this.jLabelTimer1 = jLabelTimer1; }
public TimerJFrame() { initComponents(); }
private void initComponents() {
setjLabelTimer1(new javax.swing.JLabel()); jLabelTimer2 = new javax.swing.JLabel(); jButtonStart = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getjLabelTimer1().setText("0");
jLabelTimer2.setText("10");
jButtonStart.setText("Start"); jButtonStart.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) {
try { Thread.sleep(2000); jLabelTimer1.setText(" one"); Thread.sleep(2000); jLabelTimer1.setText(" two");
} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
} });
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(60, 60, 60) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jButtonStart, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createSequentialGroup() .addComponent(getjLabelTimer1(), javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(50, 50, 50) .addComponent(jLabelTimer2, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(getjLabelTimer1()) .addComponent(jLabelTimer2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonStart) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) );
pack(); }
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new TimerJFrame().setVisible(true); } });
} public void setjLabelTimer1(String s) { this.jLabelTimer1.setText(s); }
}
|
|
| |
MINIsha | Дата: Воскресенье, 2011-10-23, 18:29:29 | Сообщение # 4 |
![MINIsha](/avatar/89/323772.jpg) Генерал-майор
Группа: Администраторы
Сообщений: 21
Статус: Offline
| Это работает !!! Code import java.awt.*; import java.awt.event.*;
import javax.swing.*;
class swingTimer { Thread g; JFrame frame; public JLabel label; JPanel panel2; String ii; ActionListener list;
public swingTimer() { //основной класс с формой frame = new JFrame("Timer");
JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3,2)); JPanel panel1 = new JPanel(); panel2 = new JPanel(); panel.add(panel1); panel.add(panel2);
JButton button = new JButton("START!"); label = new JLabel(); label.setText("Hello!"); g = new Go(); //т.к. Go() наследник Thread(), то при вызове его метода //start() создаётся новый поток и используется метод run() в котором я описал что должно //передаваться потоку; list = new ActionListener(){ @SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent ae) { try {
if ((g.getState() == Thread.State.TERMINATED)||(g.isAlive())){ //если поток живой g.interrupt(); //убить поток g.stop(); //остановить поток g=new Go();//создать новый поток } } catch (Exception e) { // System.out.println(e); // e.printStackTrace(); }
g.start(); //стартовать поток
}
}; button.addActionListener(list);
panel1.add(button); panel2.add(label);
frame.add(panel); frame.setSize(400, 400);
frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class Go extends Thread {//вложенный класс-наследник Thread swingTimer st1;
public void run(){
st1 = swingTimer.this; //обращаюсь к данному экземпляру класса for (int i = 0;i<=5; i++ ){
st1.label.setText(Integer.toString(i)); System.out.println(Integer.toString(i)); try { Thread.sleep(500); } catch (Exception e) { System.out.println(e); e.printStackTrace(); } } end = true; } } }
Code public class MainTimer { public static void main (String[] ar){ new swingTimer(); //тупо создаю экземпляр класса } }
Жду ответов!!! :D
Почему? ДА ЧЕРЕЗ ПОТОМУ КАК ЧТОЖ!
Сообщение отредактировал MINIsha - Понедельник, 2011-10-24, 09:52:51 |
|
| |
CHerry | Дата: Воскресенье, 2011-10-23, 19:15:39 | Сообщение # 5 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| Общие мысли по архитектуре такие: Должен быть класс Main откуда запускаются : один поток для swing GUI второй для таймера, третий для второго таймера и т.д.
Как создать поток, я вижу так: Code ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new MyTimer());
Как создать форму тоже понятно.
А вот как передать из класса MyTimer в элемент метку(Label) класса формы непонятно.
На других форумах предлагаю использовать JavaUtils.invoke и класс SwingWorker
|
|
| |
CHerry | Дата: Воскресенье, 2011-10-23, 22:01:10 | Сообщение # 6 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| статья про потоки и swing
|
|
| |
j_todesky | Дата: Воскресенье, 2011-10-23, 23:42:56 | Сообщение # 7 |
![j_todesky](https://171975345.uid.me/avatar.jpg) Рядовой
Группа: Проверенные
Сообщений: 18
Статус: Offline
| я тоже кое что изобразил , проанализировав Мишин текст Code import java.awt.*; import java.awt.event.*; import javax.swing.*; class SwingTimer { JTextField text; JFrame frame ; JLabel label; JLabel label1; Thread g; final Thread thr1; JTabbedPane zakladka; JPanel panel; Thread back; SwingTimer() { frame = new JFrame("Timer"); panel= new JPanel(); panel.setLayout(new GridLayout(4,4)); label= new JLabel("time"); label1 = new JLabel("backtime"); JLabel label3 = new JLabel("sec "); JLabel label4 = new JLabel("sec "); thr1 = new Thread(); JPanel panel1 =new JPanel(); JPanel panel2= new JPanel(); JPanel panel3= new JPanel(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); g = new Go(); back = new BackTimer(); JButton jStartBack = new JButton("STARTBackTIMER!"); jStartBack.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae) { try {
if ((back.getState() == Thread.State.TERMINATED)||(back.isAlive())){ back.interrupt(); //back.stop(); back=new BackTimer(); } } catch (Exception e) { } back.start(); } }); JButton jStart = new JButton("START!"); jStart.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae) { try {
if ((g.getState() == Thread.State.TERMINATED)||(g.isAlive())){ g.interrupt(); //g.stop(); g=new Go(); } } catch (Exception e) { } g.start(); } }); JButton jPause = new JButton("PAUSE!"); jPause.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae) { g.suspend();
} }); JButton jStopBackCount = new JButton("StopBackCount"); jStopBackCount.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae) { back.suspend(); } }); panel2.add(label); panel2.add(label3) ; panel2.add(label1); panel2.add(label4) ; panel3.add(jStart); panel3.add(jStartBack); panel1.add(jPause); panel1.add(jStopBackCount); panel.add(panel3); panel.add(panel1); panel.add(panel2); frame.add(panel); frame.setSize(300,300); frame.setVisible(true); frame.setBackground(Color.red); } class BackTimer extends Thread{ SwingTimer st2; public void run (){ st2= SwingTimer.this; for (int i=25;i>0; i--) { st2.label1.setText(Integer.toString(i)); System.out.println(Integer.toString(i)); try{ Thread.sleep(1000); } catch(Exception e){} } } } class Go extends Thread{ SwingTimer st1; public void run() { st1 = SwingTimer.this; for (int i = 0;; i++ ) { st1.label.setText(Integer.toString(i)); System.out.println(Integer.toString(i)); try { Thread.sleep(1000); } catch (Exception e) { // System.out.println(e); // e.printStackTrace(); } } } } } public class Main { public static void main(String[] args) { new SwingTimer(); } }
|
|
| |
CHerry | Дата: Понедельник, 2011-10-24, 10:39:59 | Сообщение # 8 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| Кстати методы suspend() помечены как Deprecated. А чем же их заменить ?
|
|
| |
MINIsha | Дата: Понедельник, 2011-10-24, 12:10:53 | Сообщение # 9 |
![MINIsha](/avatar/89/323772.jpg) Генерал-майор
Группа: Администраторы
Сообщений: 21
Статус: Offline
| Quote (CHerry) Кстати методы suspend() помечены как Deprecated. А чем же их заменить ?
прочтите это
или
вот это
очень познавательно!Добавлено (2011-10-24, 12:10:53) ---------------------------------------------
Quote (CHerry) статья про потоки и swing
Кстати, здесь рассказывается о моей программе:
... где вместо того, чтобы блокировать поток событий пока не завершится метод wait, создается анонимный внутренний класс, который расширяет java.lang.Thread, который будет вызывать для нас метод wait. В этой версии кода, событие больше не будет ждать завершения метода wait, а просто вернет управление остальному приложению (передаче собития другим слушателям) после того, как новый поток инициализировался и запустился. В результате имеем быструю реакцию на события и не заторможенную работу GUI.
Почему? ДА ЧЕРЕЗ ПОТОМУ КАК ЧТОЖ!
Сообщение отредактировал MINIsha - Понедельник, 2011-10-24, 11:56:42 |
|
| |
CHerry | Дата: Понедельник, 2011-10-24, 13:23:17 | Сообщение # 10 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| В этих статьях описана работа устаревшей модели потоков, в коментах пишут что это статья 1996. я так понял, за эти годы методы приостановления потоков оказались не безопасны и сейчас не используются. Как же быть?
|
|
| |
CHerry | Дата: Воскресенье, 2011-10-30, 18:23:52 | Сообщение # 11 |
![CHerry](/avatar/97/8071-240618.gif) Генералиссимус
Группа: Администраторы
Сообщений: 141
Статус: Offline
| Вот я созрел и дописал код используя рекомендации в Java SE5/6 а собственно: Исполнители ExecutorService вместо Thread и ожидание TimeUnit вместо Thread.sleep прорисовку GUI через поток invokeLater
Code package ua.at.javac;
import java.awt.GridLayout; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;
import javax.swing.*; public class jFrameGUI extends JFrame { /** * */ private static final long serialVersionUID = 1L; // объявляем переменную JLabel и открытый метод доступа к ней private JLabel countLabel; public void setCountLabel (String text) throws InterruptedException{ countLabel.setText(text); TimeUnit.SECONDS.sleep(1); } private JLabel timeLabel; // флаги состояния нажатых кнопок public boolean pressPause=false; public boolean pressStop=false; public boolean pressReset=false;
/** * Инициализация графического окна * */
public void initGUI() {
// создаем исполнителя exec для выполнения объекта Runnable // используем два потока для таймера и счетчика final ExecutorService exec = Executors.newFixedThreadPool(2);
// создание фрейма JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// кнопки final JButton buttonStop = new JButton("Stop"); final JButton buttonReset = new JButton("Reset"); final JButton buttonPause = new JButton("Pause"); JButton buttonStart = new JButton("Start"); buttonStop.setEnabled(false); buttonReset.setEnabled(false); buttonPause.setEnabled(false);
// слушаем кнопки Start, Stop, Reset, Pause buttonStart.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { exec.execute(new CountDown()); buttonStop.setEnabled(true); buttonPause.setEnabled(true); buttonReset.setEnabled(true); pressPause=false; pressStop=false; } } );
buttonStop.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pressStop=true; buttonStop.setEnabled(false); buttonPause.setEnabled(false); buttonReset.setEnabled(false); } } );
buttonReset.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pressReset=true; buttonStop.setEnabled(false); buttonPause.setEnabled(false); buttonReset.setEnabled(false); } } );
buttonPause.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonPause.setSelected(true); pressPause=true; buttonPause.setEnabled(false); } } );
// метки timeLabel = new JLabel("Timer"); countLabel = new JLabel("Count");
// запускаем отсчет времени и вывод в timeLabel в отдельном потоке exec.execute(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub int i=0; while(true){ i++; timeLabel.setText(""+i); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }
});
// создание табличной панели 2 строки * 3 столбца, отступы 10 * 10 JPanel panel = new JPanel(); frame.add(panel); panel.setLayout(new GridLayout(2,3,10,10));
// добавление элементов в табличную панель panel.add(timeLabel); panel.add(buttonStart); panel.add(buttonPause); panel.add(countLabel); panel.add(buttonStop); panel.add(buttonReset);
// создание формы frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //frame.setSize(300, 100); frame.pack(); frame.setTitle("Timer"); frame.setVisible(true); }
public class CountDown implements Runnable { @Override public void run() { // TODO Auto-generated method stub int i=0; while (pressStop==false){ if (pressPause==false){ i++; try { setCountLabel(""+i); // устаревшая конструкция Thread.sleep(100) // заменена на новую TimeUnit.SECONDS.sleep(1) TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } if (pressReset==true) { pressReset=false; i=0; try { setCountLabel("0"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
} }
public static void main(String[] args) {
// Создание потока для инициализации окна javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { new jFrameGUI().initGUI(); } }); //
} } [/code]
|
|
| |