在 java 中另一个线程处于 运行 时继续执行一个线程
Continue executing a thread while another thread is running in java
tl,博士;
我有一个创建另一个class对象的GUI线程(秒class已经实现了Runnable
,但是这里我们不执行run()
方法,相反,我们调用一个普通方法)并调用一个方法。在该方法中,再次调用第一个线程(当前线程)(在 LCD 上显示某事),然后将一些数据发送到 Internet,并等待 3 秒以等待服务器响应。问题是信息在 3 秒后打印出来。我知道 stack
和 program counter
,但我想知道是否还有其他选择可以完成我的工作。
我有运行 3 个线程的 main 方法(简而言之,我只写了必要的代码。如果需要,告诉我添加更多):
public static void main(String[] args) throws UnknownHostException, InterruptedException {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI.getInstance().setVisible(true); //GUI is singleton, using swing and JFrame
} catch (Exception e) {
e.printStackTrace();
}
}
});
MQTTConnection.getInstance().tryToConnect(); //It's the connection class, which has a thread (the thread is handled by a library that keeps the connection alive. I have no threads there) and is a singleton too.
Thread t1 = new Thread(new SendDataThread()); //A thread which sends some data every 20 seconds.
t1.start();
}
在 SendDataThread 中,我有一个函数可以创建一些随机数据并发送它们(使用 MQTTConnection class)。
这是SendDataThread
:
public class SendDataThread implements Runnable {
public void sendLog() {
boolean serverOnline = false;
StringBuilder data = new StringBuilder();
data.append(createData());
GUI.getInstance().printNeutral(data.toString()); //Prints BLACK on a `JTextPane`
if(MQTTConnection.getInstance().publishLog(MQTTConnection.getInstance().MQTT_PUBLISH_ESP_SEND_LOG, data.toString())) //This line has a 3 second timeout. If the server doesn't respond, it will return false. I've added the 3 seconds timeout too. Please continue reading.
serverOnline = true;
if(serverOnline)
GUI.getInstance().printOK("Server Submitted"); //Prints in GREEN
else
GUI.getInstance().printProblem("Check your connection!"); //Prints in RED
GUI.getInstance().printNeutral("-------------------------------------------------");
}
@Override
public void run() {
while(true) {
sendLog();
try {
Thread.sleep(20000); //sleeps 20 about seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//.....
}
这是3秒超时方法,在MQTTConnection
:
boolean publishLog(String topic, String data){
mqtt_responds = false;
publish(topic, data);
System.out.println("MQTT is connected");
long lastTime = System.currentTimeMillis();
while(System.currentTimeMillis() - lastTime < callback_timeout) {
if(mqtt_responds){
mqtt_responds = false;
System.out.println("Server submitted");
return true;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Timeout");
return false;
}
到目前为止,一切正常。问题开始于我在 GUI class 中有一个按钮,用户可以手动发送随机日志:
JButton sendLogBtn = new JButton("Send Log");
sendLogBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SendDataThread sdt = new SendDataThread();
sdt.sendLog();
}
});
sendLogBtn.setBounds(10, 331, 89, 23);
panel.add(sendLogBtn);
这个按钮创建一个SendDataThread
对象并调用sendLog()
方法。问题发生在这里:在调用 sendLog()
之后,sendLog()
,再次调用此 GUI 线程:
--> GUI.getInstance().printNeutral(data.toString()); //Prints BLACK on a `JTextPane`
但是3秒后打印日志(sendLog()
方法完成后,超时!)
我该如何解决这个问题?
在按钮的 actionPerformed
中,您正在呼叫 sendLog
。 sendLog
完全按照你说的做,即报告一些日志并等待大约 3 秒(假设 callback_timeout
大约等于 3000
)。
要解决此问题,您需要确保 3 秒阻塞不在 EDT 上,还要确保日志在 EDT 上 posted。
作为快速解决方法,您可以执行以下操作:
sendLogBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Thread(() -> new SendDataThread().sendLog()).start();
}
});
然后,一如既往,post 您在 EDT 中的日志,例如:
SwingUtilities.invokeLater(() -> GUI.getInstance().printNeutral(...));
和
SwingUtilities.invokeLater(() -> GUI.getInstance().printProblem(...));
和
SwingUtilities.invokeLater(() -> GUI.getInstance().printOk(...));
至于 ,我不太明白你在问什么,但我应该说(据我所知)EDT 是一个 Thread
,其中所有的 Swing 代码正在(并且应该)post 执行。这样 Swing 代码就不必是 synchronized
,因为所有与 GUI 相关的东西都是按顺序执行的(在 EDT 上)。据我所知,例如 AWT 并不打算成为单线程的。然而,Swing 是单线程的。
tl,博士;
我有一个创建另一个class对象的GUI线程(秒class已经实现了Runnable
,但是这里我们不执行run()
方法,相反,我们调用一个普通方法)并调用一个方法。在该方法中,再次调用第一个线程(当前线程)(在 LCD 上显示某事),然后将一些数据发送到 Internet,并等待 3 秒以等待服务器响应。问题是信息在 3 秒后打印出来。我知道 stack
和 program counter
,但我想知道是否还有其他选择可以完成我的工作。
我有运行 3 个线程的 main 方法(简而言之,我只写了必要的代码。如果需要,告诉我添加更多):
public static void main(String[] args) throws UnknownHostException, InterruptedException {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI.getInstance().setVisible(true); //GUI is singleton, using swing and JFrame
} catch (Exception e) {
e.printStackTrace();
}
}
});
MQTTConnection.getInstance().tryToConnect(); //It's the connection class, which has a thread (the thread is handled by a library that keeps the connection alive. I have no threads there) and is a singleton too.
Thread t1 = new Thread(new SendDataThread()); //A thread which sends some data every 20 seconds.
t1.start();
}
在 SendDataThread 中,我有一个函数可以创建一些随机数据并发送它们(使用 MQTTConnection class)。
这是SendDataThread
:
public class SendDataThread implements Runnable {
public void sendLog() {
boolean serverOnline = false;
StringBuilder data = new StringBuilder();
data.append(createData());
GUI.getInstance().printNeutral(data.toString()); //Prints BLACK on a `JTextPane`
if(MQTTConnection.getInstance().publishLog(MQTTConnection.getInstance().MQTT_PUBLISH_ESP_SEND_LOG, data.toString())) //This line has a 3 second timeout. If the server doesn't respond, it will return false. I've added the 3 seconds timeout too. Please continue reading.
serverOnline = true;
if(serverOnline)
GUI.getInstance().printOK("Server Submitted"); //Prints in GREEN
else
GUI.getInstance().printProblem("Check your connection!"); //Prints in RED
GUI.getInstance().printNeutral("-------------------------------------------------");
}
@Override
public void run() {
while(true) {
sendLog();
try {
Thread.sleep(20000); //sleeps 20 about seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//.....
}
这是3秒超时方法,在MQTTConnection
:
boolean publishLog(String topic, String data){
mqtt_responds = false;
publish(topic, data);
System.out.println("MQTT is connected");
long lastTime = System.currentTimeMillis();
while(System.currentTimeMillis() - lastTime < callback_timeout) {
if(mqtt_responds){
mqtt_responds = false;
System.out.println("Server submitted");
return true;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Timeout");
return false;
}
到目前为止,一切正常。问题开始于我在 GUI class 中有一个按钮,用户可以手动发送随机日志:
JButton sendLogBtn = new JButton("Send Log");
sendLogBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SendDataThread sdt = new SendDataThread();
sdt.sendLog();
}
});
sendLogBtn.setBounds(10, 331, 89, 23);
panel.add(sendLogBtn);
这个按钮创建一个SendDataThread
对象并调用sendLog()
方法。问题发生在这里:在调用 sendLog()
之后,sendLog()
,再次调用此 GUI 线程:
--> GUI.getInstance().printNeutral(data.toString()); //Prints BLACK on a `JTextPane`
但是3秒后打印日志(sendLog()
方法完成后,超时!)
我该如何解决这个问题?
在按钮的 actionPerformed
中,您正在呼叫 sendLog
。 sendLog
完全按照你说的做,即报告一些日志并等待大约 3 秒(假设 callback_timeout
大约等于 3000
)。
要解决此问题,您需要确保 3 秒阻塞不在 EDT 上,还要确保日志在 EDT 上 posted。
作为快速解决方法,您可以执行以下操作:
sendLogBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Thread(() -> new SendDataThread().sendLog()).start();
}
});
然后,一如既往,post 您在 EDT 中的日志,例如:
SwingUtilities.invokeLater(() -> GUI.getInstance().printNeutral(...));
和
SwingUtilities.invokeLater(() -> GUI.getInstance().printProblem(...));
和
SwingUtilities.invokeLater(() -> GUI.getInstance().printOk(...));
至于 Thread
,其中所有的 Swing 代码正在(并且应该)post 执行。这样 Swing 代码就不必是 synchronized
,因为所有与 GUI 相关的东西都是按顺序执行的(在 EDT 上)。据我所知,例如 AWT 并不打算成为单线程的。然而,Swing 是单线程的。