java中的多线程无法传递更改
我必须在应用程序线程(setReadyToUpload)中更改一个布尔变量,听到这个更改(isReadyToUpload),另一个线程(服务器线程)将做一些事情。虽然服务器线程处于while循环中,并且一直在检查,但当我在应用程序线程中更改布尔变量时,它没有捕获到更改。 应用程序线程java中的多线程无法传递更改,java,multithreading,Java,Multithreading,我必须在应用程序线程(setReadyToUpload)中更改一个布尔变量,听到这个更改(isReadyToUpload),另一个线程(服务器线程)将做一些事情。虽然服务器线程处于while循环中,并且一直在检查,但当我在应用程序线程中更改布尔变量时,它没有捕获到更改。 应用程序线程 package server; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Aler
package server;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.stage.FileChooser;
import java.io.File;
public class serverController {
serverMain main;
@FXML
private Button upload;
@FXML
private ProgressIndicator indicator;
@FXML
void pressed(ActionEvent event) {
FileChooser fc=new FileChooser();
File file=fc.showOpenDialog(main.getStage());
if(file!=null) {
main.setFileLoaction(file.getAbsolutePath());
System.out.println("it is done");
main.setReadyToUpload(true);
}
else
{
Alert alert=new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Upload problem");
alert.setContentText("You have'nt select any file to upload");
alert.showAndWait();
}
}
public void setMain(serverMain main) {
this.main = main;
}
}
服务器线程
package tcpobject;
import java.io.File;
import java.util.*;
import server.serverMain;
import util.NetworkUtil;
public class WriteThreadServer implements Runnable {
private Thread thr;
private NetworkUtil nc;
private serverMain main;
private LargeFile o;
private LargeFileInserter lfi;
String name;
public WriteThreadServer(NetworkUtil nc,String name, serverMain main) {
this.nc = nc;
this.name=name;
this.thr = new Thread(this);
this.main=main;
thr.start();
}
public void run() {
while(true)
{
try {
//System.out.println("it is "+main.isReadyToUpload());
// if i print this then thelower block works good but if i dont it cant catch the change
System.out.println("it is checking");
if(main.isReadyToUpload())
{
System.out.println("it is ru");
FileDataHandler();
}
if(main.isStartUpload()) {
//System.out.println("it is su");
LargeFileHandler();
System.out.println("it is su");
for (int i = 0; lfi.hasMoreBytes(); i++) {
o = lfi.nextByte();
nc.write(o);
}
lfi.close();
}
} catch(Exception e) {
System.out.println (e+" here");
e.printStackTrace();
nc.closeConnection();
}
}
}
void FileDataHandler ()
{
FileDataMessage fd=new FileDataMessage(main.getFileLoaction());
nc.write(fd);
main.setReadyToUpload(false);
}
void LargeFileHandler ()
{
try {
lfi=new LargeFileInserter(main.getFileLoaction());
} catch (Exception e) {
e.printStackTrace();
}
//FileDataMessage fd=new FileDataMessage("F:\\L-2 T-1\\EEE 263\\Electronic devices and ckt theory- boylestad 11th edition.pdf");
//System.out.println(fd);
//System.out.println(fd.sizetoPrint());
LargeFile o;
main.setStartUpload(false);
}
}
所有函数和变量都写在主类中,两个线程都可以访问该类。如果没有剩余的代码可用,则方法
setReadyToUpload
和isReadyToUpload
在共享对象的可见性方面存在问题,这是您设置为true的标志
可能发生的情况是,两个线程在不同的内核上运行,一个线程将标志更新为true。此更新可能发生在CPU缓存内,而另一个线程在检查值时无法读取该缓存,只要更改未刷新回主内存
您可以通过以下方式修复当前设计:
a) 具有将强制更新CPU寄存器之间缓存线的volatile标志
b) 使方法同步,效果同上
然而,您应该做的是使用wait和notify,而不是在服务器线程中忙着等待并浪费CPU周期
只需创建monitor
变量,例如:
private final Object monitor = new Object();
在服务器代码中执行以下操作:
synchronized(monitor) {
monitor.wait():
}
因此,当更改准备就绪时,您可以从另一个线程通知更改,如下所示:
synchronized(monitor)
{
monitor.notify();
}
当您的客户机是主题时,服务器可以实现Observer
。这将使您只需通过观察者的界面方法update
通知更改
请注意,从理论上讲,等待
可能会被中断,因此您应该在醒来时检查是否满足条件,如果不继续等待。请您具体说明您的问题?请提供更多的代码,让您的标志
不稳定。setReadyToUpload和isReadyToUpload是否同步?您应该为这两种方法提供代码。1)永远不要忙着等待。2) 永远不要忙着等待。3) 对于由两个线程读取的变量,它需要有一个内存屏障-volatile
在这种情况下可以工作。我必须检查服务器线程中的许多变量,以便可以等待单个变量吗?(添加了代码)查看观察者模式。我认为这将帮助您更好地理解这个问题,下面是一个简单的实现:。您应该等待事件,而不是变量。在您的例子中,事件是将标志更新为true,这可以转化为观察者的更新。@enigma您的代码举例说明了编写糟糕的多线程代码的所有错误。在许多核心CPU的时代,阻塞整个CPU来测试某些变量已不像过去那样是一种容易引起火灾的罪行;但是如果我在我的代码库中看到这一点,就会使用git-bull
,并使用强有力的词语。考虑学习关于事件驱动的编程,或者至少,<代码>等待< /代码>和<代码>通知< /代码>,