用于nfc扫描仪的Java多线程
我已经开始研究java,为我的nfc扫描器创建java应用程序 到目前为止,当我按下按钮时,我能够扫描并读取uid中的标签。(它会锁定我的gui,直到找到标记为止) 我需要扫描器在我按下按钮时一直在扫描,而不锁定我的gui,然后在发现新标签时更新我的gui 然而,我从来没有尝试过多线程,所以我不知道如何让我的新线程告诉另一个当它找到一个新标记时,我该怎么做 NFC阅读器类用于nfc扫描仪的Java多线程,java,multithreading,nfc,Java,Multithreading,Nfc,我已经开始研究java,为我的nfc扫描器创建java应用程序 到目前为止,当我按下按钮时,我能够扫描并读取uid中的标签。(它会锁定我的gui,直到找到标记为止) 我需要扫描器在我按下按钮时一直在扫描,而不锁定我的gui,然后在发现新标签时更新我的gui 然而,我从来没有尝试过多线程,所以我不知道如何让我的新线程告诉另一个当它找到一个新标记时,我该怎么做 NFC阅读器类 public class NFCCardReader { final protected static char[]
public class NFCCardReader {
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
private List<CardTerminal> terminals;
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
protected NFCCardReader() {
TerminalFactory factory = null;
try {
factory = TerminalFactory.getInstance("PC/SC", null);
System.out.println(factory);
terminals = factory.terminals().list();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CardException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected String scan() {
if (terminals.isEmpty()) {
return "Ingen NFC terminaler tilgængelig";
}
CardTerminal terminal = terminals.get(0);
boolean looking = true;
String uid = "";
while (looking) {
try {
terminal.waitForCardPresent(0);
Card card = terminal.connect("*");
CardChannel channel = card.getBasicChannel();
CommandAPDU command = new CommandAPDU(new byte[] { (byte) 0xFF,
(byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x04 });
ResponseAPDU response = channel.transmit(command);
byte[] byteArray = response.getBytes();
uid = bytesToHex(byteArray);
looking = false;
} catch (CardException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return uid;
}
}
程序类
public class Program {
private Db db;
private String currentUID = "", currentText = "";
private NFCCardReader nfc;
public Program() {
db = new Db();
nfc = new NFCCardReader();
}
public String nfcScan() {
currentUID = nfc.scan();
currentText = db.getTag(currentUID);
return currentUID;
}
public String getTagText() {
return currentText;
}
public void setTag(String text) {
db.setTag(currentUID, text);
currentText = text;
}
}
MainGui类
public class MainGui extends JPanel {
private static final long serialVersionUID = -6698282232100136737L;
private Controller controller = new Controller(this);
private JFrame prg;
private SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS");
private Date date;
private String formattedDate;
protected JLabel lblUID;
protected JButton btnScan, btnSave;
protected JTextArea txaText;
public MainGui(JFrame prg) {
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\tStarting program...");
this.setLayout(null);
this.prg = prg;
initialize();
}
public void closeProgram() {
prg.dispose();
}
private void initialize() {
// initialize SETUP
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\tInitializing...");
// initialize txaTEXT
lblUID = new JLabel();
lblUID.setText("Tag UID: ");
lblUID.setSize(160, 30);
lblUID.setLocation(30, 30);
lblUID.setVisible(true);
this.add(lblUID);
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\t\tlblUID been initialized at: "
+ lblUID.getX() + "," + lblUID.getY() + "\tSize: "
+ lblUID.getWidth() + "," + lblUID.getHeight());
txaText = new JTextArea();
txaText.setSize(370, 300);
txaText.setLineWrap(true);
txaText.setWrapStyleWord(true);
txaText.setDragEnabled(false);
txaText.setLocation(30, 70);
txaText.setMargin(new Insets(5, 5, 5, 5));
txaText.setVisible(true);
this.add(txaText);
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\t\ttxaText been initialized at: "
+ txaText.getX() + "," + txaText.getY() + "\tSize: "
+ txaText.getWidth() + "," + txaText.getHeight());
btnScan = new JButton();
btnScan.setText("Scan");
btnScan.setLocation(330, 30);
btnScan.setSize(70, 30);
btnScan.setMargin(new Insets(1, 1, 1, 1));
this.add(btnScan);
btnScan.addActionListener(controller);
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\t\tbtnScan been initialized at: "
+ btnScan.getX() + "," + btnScan.getY() + "\tSize: "
+ btnScan.getWidth() + "," + btnScan.getHeight());
btnSave = new JButton();
btnSave.setText("Gem");
btnSave.setLocation(330, 380);
btnSave.setSize(70, 30);
btnSave.setMargin(new Insets(1, 1, 1, 1));
btnSave.addActionListener(controller);
this.add(btnSave);
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\t\tbtnSave been initialized at: "
+ btnSave.getX() + "," + btnSave.getY() + "\tSize: "
+ btnSave.getWidth() + "," + btnSave.getHeight());
date = new Date();
formattedDate = sdf.format(date);
System.out.println(formattedDate + "\tInitializing...COMPLETE");
}
}
创建用于运行线程的新类。然后从要运行线程的位置调用thread的
.start
方法
package test;
public class MultiThreadApp {
BackgroundThread bt = new BackgroundThread();
public MultiThreadApp() {
// TODO Auto-generated constructor stub
bt.start();
}
public static void main(String[] args) {
new MultiThreadApp();
}
private class BackgroundThread extends Thread {
@Override
public void run() {
while (true) {
System.out.println("BackgroundThreadRunning");
}
}
}
}
1/请让您的条形码阅读器类实现Runnable 2/例如,使用前面提到的Runnable启动后台线程 通过Executors.newSingleThreadExecutor().execute(…)。或者正如另一个答案所暗示的那样 3/您的UI是Swing。从条形码阅读器内部,您需要触发功能 根据SwingUtilities.invokeLater(…)更新每个读取条形码的UI。为了进行测试,您可以简单地将SwingUtilities.invokeLater(…)放入条形码读取器中。对于真正的实时解决方案,您可能希望将此逻辑放入控制器中,或者让条形码读取器触发一个动作。重要的是,条形码读取器会触发,但触发的代码在SwingUtilities.invokeLater(…)中 您还需要提供有序关闭应用程序的功能。例如,这可能是一个例子 通过使变量看起来易变并将其按setter公开给外部(UI、controller)代码来完成。UI/控制器随后可能会使用setter向后台线程发出停止读取条形码的信号
Swing教程中有关于此类编程问题的示例和解释。我认为您需要更精确地表述您的问题。我错过了以下信息:0/您需要将条形码传送到的“其他”线程是什么?UI线程?如果是,您计划使用什么用户界面?摆动1/您是否计划在循环中读取新条形码?这是您所说的,但当前您的while循环只读取一个条形码,然后结束。或者你是在寻找一种方法,一次只读取一个条形码,而不阻塞用户界面?@Michal很抱歉,我试图让它更清楚地知道我现在想要它做什么这只是简单的部分。他正在寻找传递信息的方法。然后我如何让它将找到的标记发送到我的主线程?我关于关闭应用程序的评论有一个问题-在读取条形码后首先检查looking变量。因此,在设置looking=false后,可能需要首先读取一个条形码。不幸的是,没有干净的处理方法。如果waitForCardPresent(..)接受超时,则会有所帮助。否则,您可能不得不执行System.exit(..),这不是结束应用程序的干净方法。非常感谢
package test;
public class MultiThreadApp {
BackgroundThread bt = new BackgroundThread();
public MultiThreadApp() {
// TODO Auto-generated constructor stub
bt.start();
}
public static void main(String[] args) {
new MultiThreadApp();
}
private class BackgroundThread extends Thread {
@Override
public void run() {
while (true) {
System.out.println("BackgroundThreadRunning");
}
}
}
}