gpt4 book ai didi

java - java中的多线程无法传达变化

转载 作者:行者123 更新时间:2023-11-30 03:08:46 27 4
gpt4 key购买 nike

我必须更改应用程序线程中的 boolean 变量(setReadyToUpload),并听到此更改(isReadyToUpload),另一个线程(服务器线程)将执行某些操作。虽然服务器线程处于 while 循环中并检查所有时间,但它没有捕获当我更改应用程序线程中的 boolean 变量时发生的变化。应用程序线程

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);
}

}

所有函数和变量都写在主类中,两个线程都可以访问该类。

最佳答案

在没有其余代码可用的情况下,方法 setReadyToUploadisReadyToUpload 会出现共享对象可见性问题,这是您设置为 true 的标志。

可能发生的情况是两个线程在不同的内核上运行,并且一个线程将标志更新为 true。此更新可能发生在 CPU 缓存内,只要更改未刷新回主内存,检查该值的另一​​个线程就无法读取该缓存。

您可以通过以下方式修复当前设计:

a) 具有 volatile 标志,这将强制更新 CPU 寄存器之间的缓存线

b) 使方法同步,效果与上面相同

但是,您应该做的是使用等待和通知,而不是在服务器线程中忙于等待并浪费 CPU 周期。

只需创建监视器变量,例如:

private final Object monitor = new Object();

并在服务器代码中执行以下操作:

synchronized(monitor) {

monitor.wait():
}

因此,当更改准备就绪时,您可以从另一个线程通知更改,如下所示:

synchronized(monitor)

{
monitor.notify();
}

服务器可以实现Observer,而您的客户端是Subject。这将让您只需通过 Observer 的接口(interface)方法 update 通知更改即可。

请注意,理论上 wait 可能会被中断,因此您应该在唤醒时检查条件是否满足,如果不满足则继续等待。

关于java - java中的多线程无法传达变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34117151/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com