从线程编辑变量



我正在做一个简单的项目:服务器在读取文件的线程中执行一个从属(ReaderF 类),然后提取其内容并将其保存在服务器内部。然后,服务器需要执行一个池,以便在连接时将内容发送到客户端。我首先编写了 ReaderF 来提取内容。问题:它从不编辑他应该在其中存储内容的 String 变量。这是我所做的:

public class Serveur {
private ServerSocket serverSocket;
private Socket socket;
public String res=null; //This is what my thread is supposed to be editing
ExecutorService pool = null;
public static final int port = 33333;
Serveur(int port, int size){
try {
pool = Executors.newFixedThreadPool(5);
serverSocket = new ServerSocket(port, size);            
} catch (IOException ex) {
Logger.getLogger(Serveur.class.getName()).log(Level.SEVERE, null, ex);
}
}
void manage () throws IOException {
while(true) {
ReaderF S = null;
try {
S = new ReaderF(serverSocket.accept(), this);
} catch (IOException e) {
e.printStackTrace();
}
Thread t=new Thread(S);
t.start();
}
}

这是读取和编辑 res 变量的从属服务器。

public class ReaderF implements Runnable {
private final Socket socket;
private Serveur serverMaitre;
ReaderF(Socket socket, Serveur serverMaitre) {
this.socket = socket;
this.serverMaitre = serverMaitre;
}

public void run() {
String fileName = "/home/abdou/1.txt";
FileReader fileReader = null;
Writer output =null;
try {
fileReader = new FileReader(fileName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
output = new OutputStreamWriter(socket.getOutputStream(), "8859_1");
String line;
String res="";
while((line = bufferedReader.readLine()) != null) {
res+=line+"n";   
}
serverMaitre.res=res; // This is where i tell him to edit res inside the server
socket.close();
} catch (IOException e) {
e.printStackTrace();
}

}

当我执行这个主要内容时,我在屏幕上看不到任何东西。我知道这是因为服务器卡在 while 循环中。

public class Main{
public static void main(String[] args) throws IOException {
Serveur serveur = new Serveur(Serveur.port, 1);
serveur.manage();
System.out.println("The res variable content is"+serveur.res);
}}

请问我该如何摆脱它。我的线程真的改变了 res 变量吗?谢谢

当多个线程使用相同的变量时,允许它们处理变量的本地副本(在其堆栈中)而不是原始变量(在堆中)。这意味着一个线程可能看不到另一个线程所做的变量更改(他没有"刷新"其本地数据),或者另一个线程没有"发布"(技术术语:刷新)更新的值。因此,当您的 ReaderF 为"res"赋值时,主线程(正在检查它)可能不会注意到这一点。解决方案:将变量设为volatile

public volatile String res=null;

这会强制 ReaderF 在分配后刷新更新的值,并强制主线程在读取时刷新它。

但是你可能在这里遇到另一个问题,因为你有多个线程可能都在写入'res'变量(取决于套接字的活动程度)。您可以在此处获得"丢失更新"或其他"竞争条件"。所以也许你甚至需要在某个地方synchronized。但是在这里解释多线程就太过分了。请谷歌一下。不幸的是,多线程并非易事,您不能随心所欲地创建新线程并期望一切正常。大多数时候,添加易失性并不是解决方案。对于您想在这里做的事情来说,这可能就足够了。

最新更新