Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Оптимизация потока


Автор: x3bytes 10.11.2006, 22:24
Код

package testapp;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;


public class PicPanel extends JPanel implements Runnable{
    Image image;
    boolean mousePressed=false; //флаг показывающий когда клавиша мыши нажата
    
    JFrame pMain;
    public Thread thread = null; //Главный поток
    
    public PicPanel(String source, JFrame pM){
        String file = source;
        pMain = pM;
        try{
            image = super.getToolkit().getImage(this.getClass().getResource(file));
        } catch(Exception e){
            JOptionPane.showMessageDialog(this, e.getMessage());
            System.out.println(e.getMessage());
        }
        
        thread = new Thread(this);
    
    this.setCursor(new Cursor(Cursor.HAND_CURSOR));
    
    //Обработчики событий мыши
    this.addMouseListener(new MouseAdapter() {
        //Invoked when a mouse button has been pressed on a component.
        public void mousePressed(MouseEvent event) {
            mousePressed=true;
            int i=0;   
            thread.start();                        
            
        }
        
        //Invoked when a mouse button has been released on a component.
        public void mouseReleased(MouseEvent event) {
            mousePressed=false;
            
        }
        
        //Invoked when the mouse button has been clicked (pressed
        //and released) on a component.
        public void mouseClicked(MouseEvent e){}
        
        //Invoked when the mouse enters a component.
        public void mouseEntered(MouseEvent e){}
        
        //Invoked when the mouse exits a component.
        public void mouseExited(MouseEvent e){}
        
    });
    this.addMouseMotionListener(new MouseMotionListener() {
        //Invoked when the mouse cursor has been moved onto a component
        //but no buttons have been pushed.
        public void mouseMoved(MouseEvent event){
        }
        
        //Invoked when a mouse button is pressed on a component and then
        //dragged.
        public void mouseDragged(MouseEvent e) {
        }
    }
    );
}

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g = g.create();
    g.drawImage(image, 0, 0, this);
}

public void run() {
    thread = Thread.currentThread();
    for(int i=0;mousePressed==true;i++){
        pMain.setTitle("i = "+i);
    }
    thread = new Thread(this);
}

}


Здесь создаётся поток. Тоесть при нажатии на  JPanel у окна которое содержит этот JPanel начинает крутится счётчик в заголовке окна.
Грубо говоря пример эммуляции зажатия кнопки мыши на объекте(ведь в этом JPanel может быть рисованая кнопка)

Мой вопрос про оптимизацию потока. Вроде всё работает, но если подумать то когда мы не нажимаем на JPanel наш поток надо приостанавливать(зачем зря будет работать). Потом запуск реализуется коммандой start() и постоянно вызывается при нажатии мышки. Правильно ли это? Как я знаю надо только 1 раз вызывать start() при запуске потока.
Я пытался разобраться с wait() yield() и suspend() но чтот безрезультатно. Может ктот приведёт код правильного использования этих комманд?

Можно ли реализовать поток независимо от этого класса Runnable типа:
Код

Thread thread = new Thread(new Runnable(){
public void run(){
for(int i=0;mousePressed==true;i++){
            pMain.setTitle("i = "+i);
        }
}
});

так как если заменить этим кодом строчку 
Код

thread = new Thread(this);

то при повторном нажатии на JPanel выскочит ошибка 
at java.lang.Thread.start(Thread.java:571)

Автор: LSD 10.11.2006, 23:41
1. Сделай так:
Код
  private final Object lock = new Object();
  private boolean fullStop = false;
  private boolean work = false;

  public void run()
  {
    while(!fullStop)
    {
      while(work)
      {
        //do work here
      }
      try
      {
        synchronized(lock)
        {
          lock.wait();
        }
      }
      catch(InterruptedException e)
      {
      }
    }
  }

когда тебе надо выполнить какую-то работу делаешь так:
Код
work = true;
synchronized(lock)
{
  lock.notifyAll();
}

когда закончишь:
Код
work = false;

когда необходимость выполнять действия отпадет вообще (окно будет закрыто, выход из приложения и т.п.):
Код
fullStop = true;
work = false;
synchronized(lock)
{
  lock.notifyAll();
}


2. Когда идет доступ к компонентам Swing из другого потока, надо использовать такой метод:
Код
SwingUtilities.invokeLater(new Runnable()
{
  public void run()
  {
    pMain.setTitle("Бла-бла-бла");
  }
});


3.
Цитата(x3bytes @  10.11.2006,  22:24 Найти цитируемый пост)
то при повторном нажатии на JPanel выскочит ошибка at java.lang.Thread.start(Thread.java:571)

Это не ошибка, это ее кусок, по которому невозможно, что-то понять.

Автор: x3bytes 11.11.2006, 18:10
Спасибо огромное тебе LSD !!!  smile 
Столько перерыл справок и не смог по ним сделать работующую прогу.
А по твоим словам сразу получилось.

Привожу пример изменёной программы. Теперь я так понимаю всё сделано как надо и процесс пока он не нужен не обрабатывается процессором. 

Код

package testapp;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;


public class PicPanel extends JPanel{
    
    
    private boolean fullStop = false;
    private boolean work = false;
    
    int i=0;
    Image image;
    
    JFrame pMain;
    public Thread thread = null; 
    
    public PicPanel(String source, JFrame pM){
        String file = source;
        pMain = pM;
        try{
            image = super.getToolkit().getImage(this.getClass().getResource(file));
        } catch(Exception e){
            JOptionPane.showMessageDialog(this, e.getMessage());
            System.out.println(e.getMessage());
        }
        
        thread = new Thread(new Runnable(){
            public void run(){
                
                
                while(!fullStop) {    
                    while(work) {
                        i++;
                        pMain.setTitle("i = "+i);
                    }
                    try {
                        synchronized(thread) {
                            thread.wait();
                        }
                    } catch(InterruptedException e) {
                    }
                }
            }
            
        });
        
        thread.start();
        
        this.setCursor(new Cursor(Cursor.HAND_CURSOR));
        
        //Обработчики событий мыши
        this.addMouseListener(new MouseAdapter() {
            //Invoked when a mouse button has been pressed on a component.
            public void mousePressed(MouseEvent event) {
                
                work = true;
                synchronized(thread) {
                    thread.notifyAll();
                }

            }
            
            //Invoked when a mouse button has been released on a component.
            public void mouseReleased(MouseEvent event) {
                
                work = false;

            }
            
            //Invoked when the mouse button has been clicked (pressed
            //and released) on a component.
            public void mouseClicked(MouseEvent e){}
            
            //Invoked when the mouse enters a component.
            public void mouseEntered(MouseEvent e){}
            
            //Invoked when the mouse exits a component.
            public void mouseExited(MouseEvent e){}
            
        });
        this.addMouseMotionListener(new MouseMotionListener() {
            //Invoked when the mouse cursor has been moved onto a component
            //but no buttons have been pushed.
            public void mouseMoved(MouseEvent event){
            }
            
            //Invoked when a mouse button is pressed on a component and then
            //dragged.
            public void mouseDragged(MouseEvent e) {
            }
        }
        );
    }
    
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g = g.create();
        g.drawImage(image, 0, 0, this);
    }
    
    protected void Destroy(){
        fullStop = true;
        work = false;
        synchronized(lock) {
            lock.notifyAll();
        }
    }
    
}


правда не совсем понял практическое применение invokeLater()

Автор: powerOn 11.11.2006, 18:16
Цитата(x3bytes @  11.11.2006,  18:10 Найти цитируемый пост)
правда не совсем понял практическое применение invokeLater() 

http://forum.vingrad.ru/topic-50027.html

Автор: LSD 11.11.2006, 18:20
invokeLater() нужен для того чтобы выполнять действия в потоке обработки сообщений AWT.
Если мы будем одновременно из разных потоков менять данные, то может нарушится их целостность. Выхода два: синхронизировать доступ к данным, или делать все из одного потока. Синхронизация плоха тем, что замедляет скорость работы (синхронизированный вызов функции ощутимо дольше, не синхронизированного), поэтому для Swing был выбран второй метод (такой же подход выбран и для SWT, и для WindowsForms), а invokeLater() это просто способ его реализации.

Автор: x3bytes 13.11.2006, 04:25
А можно пример с оптимизацией на основе кода(приведеного выше) с использованием этой функции?
У меня всю дорогу только получается завесить приложение этой функцией.

Автор: LSD 13.11.2006, 09:29
Я тебе уже дал пример как надо его использовать. Ты его пробовал?

Автор: x3bytes 13.11.2006, 20:14
Да спасибо!
Спасибо за помощь  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)