简体   繁体   English

Java Swing Keylistener和线程

[英]java swing keylistener and threads

no, this is not the general question about threadsafety and adding of keylisteners :) 不,这不是关于线程安全和添加密钥侦听器的一般问题:)

I encountered a strange problem when switching a boolean on and off by using a keylistener in swing: I turn the boolean on and off when the key is pressed and released. 在摆动中使用键侦听器打开和关闭布尔值时遇到一个奇怪的问题:按下和释放键时,打开和关闭布尔值。 In another thread, I read the value of the boolean and want to do something with it. 在另一个线程中,我读取了布尔值,并希望对其进行处理。 But somehow the if block is not being accessed though the value of the boolean must be true because I am holding the key. 但是以某种方式,尽管布尔值必须为true,但无法访问if块,因为我握住了键。 If I add breakpoints to this section, the breakpoint does get accessed, or if I add a sleep inside the if block. 如果我在本节中添加断点,则确实可以访问该断点,或者如果我在if块中添加了sleep。 Why is this happening? 为什么会这样呢? Can someone explain? 有人可以解释吗?

EDIT: Strange. 编辑:奇怪。 Using an AtomicBoolean solves the issue. 使用AtomicBoolean可解决此问题。 Could this be a live lock? 这可以是活锁吗?

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();
    }
}

I think you can use the outer doIt variable with 'Test.doIt'. 我认为您可以将外部doIt变量与“ Test.doIt”一起使用。

In general you use OuterClassName.this to refer to the enclosing instance of the outer class. 通常,您使用OuterClassName.this来引用外部类的封闭实例。

I guess you should try a setter and a local variable in the thread(). 我猜您应该在thread()中尝试使用setter和局部变量。 This may need a new class. 这可能需要一个新的类。 So everytime 'doit' changes you do like classname.setBool(doit). 因此,每次“ doit”更改时,您都会喜欢classname.setBool(doit)。 I'm not sure if it's working but it would be a nice start :) 我不确定它是否正常工作,但是这将是一个不错的开始:)

I'm not very experienced with threads, but i would say "doIt" is not thread-safe. 我对线程不是很有经验,但是我会说“ doIt”不是线程安全的。

You could also use volatile : volatile private boolean doIt = false; 您还可以使用volatilevolatile private boolean doIt = false; This will solve this issue. 这样可以解决这个问题。 The volatile makes java always to re-read the value from memory, not caching or something.. volatile使Java总是从内存中重新读取值,而不是缓存或其他内容。

But that's all i know. 但这就是我所知道的。 I hope someone can give a better explanation. 我希望有人能给出更好的解释。

I would prefer AtomicBoolean because i've always read something like: "don't use volatile if you don't really need to do" and that's what AtomicBoolean is made for. 我更喜欢AtomicBoolean,因为我一直读着这样的东西:“如果不需要,请不要使用volatile”,这就是AtomicBoolean的用途。

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

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