Java:实现一个新线程,现在我的代码执行两次

时间:2012-01-19 20:23:24

标签: java multithreading observer-pattern

我前几天问了一个关于在摆动GUI中获取键盘输入的问题 - 实际上是MCR输入。一位用户发现了某人编写的低级键盘钩子。非常酷,它主要起作用。我必须学习一些新东西来实现它(总是很乐意这样做),而且我可能无法完全理解正在发生的事情。

事情是,并且我将发布下面的代码,当我实现键盘钩子的线程时,它现在运行一次while循环(而在CardRead.java中成功== false)。如果我硬编码样本数据,它只运行一次。如果我删除键盘钩子并使用普通的Scanner.nextLine()(这意味着我必须在控制台中单击以向应用程序提供输入),它只运行一次。用键盘输入观察者开始一个新线程?两次。我不明白为什么,或如何解决它。我很高兴只是明白究竟发生了什么 - 如果你们中的一个人告诉我如何修复它,我会欣喜若狂。

以下是代码:

CardRead.java

public class CardRead {

public static String raw_card_data;

int readcount = 1;

String[] tracks = new String[2];
String[] tracks_final = new String[2];

public static void main() 
{
    // This doesn't happen until after card is swiped, dunno why.
    //GUI.outputArea.setText(GUI.outputArea.getText() + "\n\n Scan card \n");

    boolean success = false;

    while (success == false)
    {
        //raw_card_data = "%test?;testing?"; // <-- using this, runs thru once

        // using THIS, runs through twice.
        // create an event source - reads from stdin
        final KB_EventSource evSrc = new KB_EventSource();

        // create an observer
        final KB_RespHandler respHandler = new KB_RespHandler();

        // subscribe the observer to the event source
        evSrc.addObserver( respHandler );

        // starts the event thread
        Thread kb_thread = new Thread(evSrc);
        kb_thread.start();

        // sleep until card swiped
        while (raw_card_data == null)
        {
            try
            {
                Thread.sleep(1000);

            }
            catch (Exception e)
            {
                System.out.println(e.getMessage());
            }
        }
        System.out.println(raw_card_data);

                // Tokenize raw_card_data
        StringTokenizer tokenizer = new StringTokenizer(raw_card_data, "?");
        int i = 0;
        do
        {
            tracks[i] = tokenizer.nextToken();
            System.out.println(i + ": " + tracks[i]);
            i++;
        }
        while (tokenizer.hasMoreTokens());
        //System.out.println(track1);
        //System.out.println(track2);
        tracks_final[0] = tracks[0].substring(1,tracks[0].length());
        if (tracks[1] != null)
        {
            tracks_final[1] = tracks[1].substring(1,tracks[1].length());
        }   
        if ( (readcount <= 5) && ( (tracks_final[0].equals("E") || tracks_final[0].equals(null) ) || (tracks_final[1].equals("E") || tracks_final[1].equals(null)) ) )
        {
            GUI.notout.setText("Card Read Unsuccessful. Scan Again.");
            GUI.outputArea.setText(GUI.outputArea.getText() + "Card read unsuccessful. Scan again. \n");
            success = false;
            readcount++;
        }
        else if (readcount <= 5)
        {
            GUI.notout.setText("Card Successfully Read");
            GUI.outputArea.setText(GUI.outputArea.getText() + "\n Success! \n");
            GUI.outputArea.setText(GUI.outputArea.getText() + "Track 1 = " + tracks_final[0] + "\n");
            GUI.outputArea.setText(GUI.outputArea.getText() + "Track 2 = " + tracks_final[1] + "\n");
            success = true;
        } // end if else chain
       } // end while success == false
} // end public void main
} // end class CardRead

KB_RespHandler.java

import java.util.Observable;
import java.util.Observer;

public class KB_RespHandler implements Observer 
{
private String resp;
    public void update (Observable obj, Object arg)
    {
        if (arg instanceof String) 
        {
            resp = (String) arg;
            CardRead.raw_card_data = resp;           
        }
    }
}

KB_EventSource.java

import de.ksquared.system.keyboard.*;
import java.util.Observable; 

public class KB_EventSource extends Observable implements Runnable
{
public static String temp = "";
public static String output = "";

public void run() 
{   

    new GlobalKeyListener().addKeyListener(new KeyAdapter() 
    {
        @Override public void keyPressed(KeyEvent event)
        { 
            switch(event.getVirtualKeyCode())
            {
            case KeyEvent.VK_0:
                if (event.isShiftPressed() == true)
                    temp += ")";
                else if (event.isShiftPressed() == false)
                    temp += "0";
                break;
            case KeyEvent.VK_1:
                if (event.isShiftPressed() == true)
                    temp += "!";
                else if (event.isShiftPressed() == false)
                    temp += "1";
                break;
            /*insert processing for other keys here*/
            case KeyEvent.VK_SPACE:
                if (event.isShiftPressed() == true)
                    temp += " ";
                else if (event.isShiftPressed() == false)
                    temp += " ";
                break;
            case KeyEvent.VK_RETURN:
                /*if (event.isShiftPressed() == true)
                    temp += "\n";
                else if (event.isShiftPressed() == false)
                    temp += "\n";*/
                setChanged();
                notifyObservers(temp);
                //clearChanged();
                  break;                                                                        
            } // end switch (event.getVirtualKeyCode())*/
        } // end public void keyPressed
    });
    while(true)
    try 
    { 
        Thread.sleep(100); 
    }
    catch(InterruptedException e) 
    { 
        e.printStackTrace(); 
    }
}
} 

所以,我不知道发生了什么。我想也许我需要在收到输入后停止线程kb_thread,但我找不到任何方法来做到这一点。不推荐thread.stop()thread.destroy(),Eclipse和Google告诉我不要使用它们。这甚至可能不是我需要做的事情。

1 个答案:

答案 0 :(得分:0)

“CardRead.java”中的评论说“成功后哪个会改变成功=真实”。

这是否意味着它可能会失败,因此它不会改变success

如果这是真的那么raw_card_data仍然是非空的,它会再试一次。

我假设你在某个时候再次将raw_card_data重置为null。

另一方面,这个:

if (event.isShiftPressed() == true)
    temp += ")";
else if (event.isShiftPressed() == false)
    temp += "0";

可以简化为:

if (event.isShiftPressed())
    temp += ")";
else
    temp += "0";