2015-06-22 2 views
2

Я использую прослушиватель мыши для мыши, нажатой и отпущенной. Когда мышь нажата, я хочу, чтобы счетчик увеличивал переменную, и когда мышь выпущена, я хочу уменьшить эту переменную. Прямо сейчас, мой код работает и делает это, но приращение идет слишком быстро, я хотел замедлить его, потому что я использую эти числа для координат в игре. Я попытался добавить Thread.sleep (100), но я получал искаженные результаты. Похоже, что сразу несколько потоков собрались, и у меня были номера повсюду. Ниже приведен пример кода.Глядя на приостановку потока с помощью thread.sleep

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JButton; 
import java.awt.event.*; 
import java.awt.event.ActionListener; 
import java.lang.*; 

public class Sample extends JFrame { 
    private JPanel jp = new JPanel(); 

    int i = 0; 
    boolean once = true; 
    boolean on = true; 

    Thread t1 = new Thread(new Increase()); 
    Thread t2 = new Thread(new Decrease()); 

    public sample() { 
     setVisible(true); 
     setSize(300, 300); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 

     add(jp); 

     addMouseListener(new MouseAdapter() { 
      public void mousePressed(MouseEvent event) { 
       if (!once) //false 
       { 
        t2.interrupt(); 
       } 

       if (once) //true 
       { 
        once = false; 
        t1.start(); 
       } 
       else { 
        t1 = new Thread(new Increase()); 
        t1.start(); 
       } 
      } 

      public void mouseReleased(MouseEvent event) { 
       t1.interrupt(); 
       if (on) //true 
       { 
        on = false; 
        t2.start(); 
       } 
       else { 
        t2 = new Thread(new Decrease()); 
        t2.start(); 
       } 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     new Sample(); 
    } 

    public int getI() { 
     return i; 
    } 

    public void setI(int num) { 
     i = num; 
    } 

    class Increase implements Runnable { 
     public void run() { 
      int num = getI(); 
      while (!Thread.currentThread().isInterrupted()) { 
       try { 
        setI(++num); 
        Thread.sleep(100); 
        System.out.println(num); 
       } 
       catch (InterruptedException e) { 
       } 
      } 
     } 
    } 

    //Thread.currentThread().isInterrupted() 
    class Decrease implements Runnable { 
     public void run() { 
      int num = getI(); 
      while (!Thread.currentThread().isInterrupted()) { 
       try { 
        setI(--num); 
        Thread.sleep(100); 
        System.out.println(num); 
       } 
       catch (InterruptedException e) { 
       } 
      } 
     } 
    } 
} 
+0

Зачем вам нужен 'Thread'? Кроме того, потоки не являются повторными, то есть вы не можете перезапустить их после их выхода. – MadProgrammer

+0

Вы можете использовать одиночный Swing 'Timer' и значение delta для достижения того же, безопасно – MadProgrammer

+0

Код работает так, как вы написал его. – Rishav

ответ

5

Вы, вероятно, работаете в состояние гонки между двумя нитями, тот факт, что i не летучая также предполагает, что потоки не могут работать с одной и той же фактической стоимостью, как друг с другом.

Резьбы также являются не реентерабельными, что означает, что как только существует метод run, их нельзя перезапустить.

Вы можете добиться того же результата, просто используя один Thread и значение «дельта» (или изменения).

В следующем примере используется Swing Timer, так как это проще и позволяет мне безопасно обновлять пользовательский интерфейс, но принцип тот же.

Counter

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private JLabel label; 
     private Timer timer; 
     private int value = 0; 
     private int delta = 1; 

     public TestPane() { 
      setLayout(new GridBagLayout()); 
      label = new JLabel("0"); 
      add(label); 
      addMouseListener(new MouseAdapter() { 

       @Override 
       public void mousePressed(MouseEvent e) { 
        delta *= -1; 
       } 

       @Override 
       public void mouseReleased(MouseEvent e) { 
        delta *= -1; 
       } 

      }); 

      timer = new Timer(100, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        setValue(getValue() + delta); 
       } 
      }); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     public int getValue() { 
      return value; 
     } 

     public void setValue(int value) { 
      this.value = value; 
      label.setText(Integer.toString(value)); 
     } 

    } 

} 

Обновленный с двумя «потоками»

И только потому, что я совсем с ума, и это приятно, чтобы продемонстрировать дополнительную нагрузку. В этом примере используются два Thread с.

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.concurrent.atomic.AtomicBoolean; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel implements Value { 

     private JLabel label; 
     private volatile int value = 0; 

     private ManipulateRunner incrementRunner; 
     private ManipulateRunner decrementRunner; 

     private Thread incrementThread; 
     private Thread decrementThread; 

     public TestPane() { 

      incrementRunner = new ManipulateRunner(this, 1); 
      decrementRunner = new ManipulateRunner(this, -1); 

      setLayout(new GridBagLayout()); 
      label = new JLabel("0"); 
      add(label); 
      addMouseListener(new MouseAdapter() { 

       @Override 
       public void mousePressed(MouseEvent e) { 

        decrementRunner.pause(); 
        if (incrementThread == null) { 
         incrementThread = new Thread(incrementRunner); 
         incrementThread.start(); 
        } 

        incrementRunner.resume(); 

       } 

       @Override 
       public void mouseReleased(MouseEvent e) { 

        incrementRunner.pause(); 
        if (decrementThread == null) { 
         decrementThread = new Thread(decrementRunner); 
         decrementThread.start(); 
        } 

        decrementRunner.resume(); 

       } 

      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     public int getValue() { 
      return value; 
     } 

     @Override 
     public void setValue(final int value) { 
      if (EventQueue.isDispatchThread()) { 
       this.value = value; 
       label.setText(Integer.toString(value)); 
      } else { 
       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         setValue(value); 
        } 
       }); 
      } 
     } 

    } 

    public static interface Value { 

     public int getValue(); 

     public void setValue(int value); 
    } 

    public static class ManipulateRunner implements Runnable { 

     protected final Object pauseLock = new Object(); 
     private int delta; 
     private AtomicBoolean paused = new AtomicBoolean(false); 
     private AtomicBoolean stopped = new AtomicBoolean(false); 
     private Value value; 

     public ManipulateRunner(Value value, int delta) { 
      this.delta = delta; 
      this.value = value; 
     } 

     public void pause() { 

      if (!paused.get() && !stopped.get()) { 

       paused.set(true); 
       synchronized (pauseLock) { 
        pauseLock.notify(); 
       } 

      } 

     } 

     public void resume() { 

      if (paused.get() && !stopped.get()) { 

       paused.set(false); 
       synchronized (pauseLock) { 
        pauseLock.notify(); 
       } 

      } 

     } 

     public void stop() { 

      if (!stopped.get()) { 

       stopped.set(true); 
       synchronized (pauseLock) { 
        pauseLock.notify(); 
       } 

      } 

     } 

     @Override 
     public void run() { 

      while (!stopped.get()) { 

       while (!stopped.get() && paused.get()) { 
        synchronized (pauseLock) { 
         try { 
          pauseLock.wait(); 
         } catch (InterruptedException ex) { 
         } 
        } 
       } 

       if (!stopped.get()) { 
        value.setValue(value.getValue() + delta); 

        try { 
         Thread.sleep(100); 
        } catch (InterruptedException ex) { 
        } 
       } 

      } 

     } 

    } 

} 

Лично решение, которое является наиболее простым и работает, является лучшим решением, но это мне

+0

Спасибо, это похоже на гораздо лучшее решение –

+0

@SpencerSprowls Да, решение, которое является самым простым и работает, как правило, является лучшим решением ;) – MadProgrammer

+0

Может ли кто-нибудь указать причину падения? – MadProgrammer

Смежные вопросы