簡體   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