java - 希望使用 thread.sleep 暂停线程

标签 java multithreading

我正在使用鼠标监听器来按下和释放鼠标。当按下鼠标时,我想要一个递增变量的计数器,而当松开鼠标时,我想要递减该变量。现在,我的代码正在运行,但增量太快了,我想减慢它的速度,因为我在游戏中使用这些数字作为坐标。我尝试添加一个 Thread.sleep(100) 但我得到的是倾斜的输出。看起来好像有多个线程在同时运行,而且我到处都是数字。下面是示例代码。

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) {
                }
            }
        }
    }
}

最佳答案

您可能遇到了两个线程之间的竞争条件,i 不是可变的这一事实也表明线程可能不会使用彼此相同的实际值。

线程也是不可重入的,也就是说一旦run方法存在,就不能重新启动。

您只需使用一个 Thread 和一个“增量”(或更改)值即可获得相同的结果。

以下示例使用 Swing Timer,因为它更简单并且允许我安全地更新 UI,但原理是相同的。

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) {
                    }
                }

            }

        }

    }

}

就个人而言,最简单有效的解决方案是更好的解决方案,但我就是这样

关于java - 希望使用 thread.sleep 暂停线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30990477/

相关文章:

ios - AFNetworking 究竟是如何工作的?

java - Android:File()的 Assets 文件夹路径?

java - Moxy 忽略 json 中的无效字段

java - 基于 Hibernate 中的某些条件的两个日期列中的日期

java - 我应该如何处理 Java 中的多线程?

c - 如何使用它来杀死线程数组?

iOS的dispatch_get_global_queue嵌套在dispatch_get_main_queue中

java - 从 db2 获取结果集

java - 如何在我的 Controller Spring Boot 中获取输入表单中的值

c++ - 如何从dll中的异步函数返回值