繁体   English   中英

Java Swing Keylistener和线程

[英]java swing keylistener and threads

不,这不是关于线程安全和添加密钥侦听器的一般问题:)

在摆动中使用键侦听器打开和关闭布尔值时遇到一个奇怪的问题:按下和释放键时,打开和关闭布尔值。 在另一个线程中,我读取了布尔值,并希望对其进行处理。 但是以某种方式,尽管布尔值必须为true,但无法访问if块,因为我握住了键。 如果我在本节中添加断点,则确实可以访问该断点,或者如果我在if块中添加了sleep。 为什么会这样呢? 有人可以解释吗?

编辑:奇怪。 使用AtomicBoolean可解决此问题。 这可以是活锁吗?

package de.osipovan.rccontroller.gui;

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Test extends JFrame implements KeyListener {

    private static final long serialVersionUID = -8395585938567486151L;

    private JPanel contentPane;
    private boolean doIt = false;
    private Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            while(true){
                if(doIt){
                    System.out.println("done");
//                  try {
//                      Thread.sleep(10);
//                  } catch (InterruptedException e) {
//                      // TODO Auto-generated catch block
//                      e.printStackTrace();
//                  }
                }
            }
        }
    });

    public Test (){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        t.start();

        addKeyListener(this);
        contentPane.addKeyListener(this);

        setVisible(true);
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_UP){
            doIt = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_UP){
            doIt = false;
        }
    }

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

我认为您可以将外部doIt变量与“ Test.doIt”一起使用。

通常,您使用OuterClassName.this来引用外部类的封闭实例。

我猜您应该在thread()中尝试使用setter和局部变量。 这可能需要一个新的类。 因此,每次“ doit”更改时,您都会喜欢classname.setBool(doit)。 我不确定它是否正常工作,但是这将是一个不错的开始:)

我对线程不是很有经验,但是我会说“ doIt”不是线程安全的。

您还可以使用volatilevolatile private boolean doIt = false; 这样可以解决这个问题。 volatile使Java总是从内存中重新读取值,而不是缓存或其他内容。

但这就是我所知道的。 我希望有人能给出更好的解释。

我更喜欢AtomicBoolean,因为我一直读着这样的东西:“如果不需要,请不要使用volatile”,这就是AtomicBoolean的用途。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM