从线程编辑变量

时间:2018-04-08 19:53:28

标签: java multithreading sockets

我正在开发一个简单的项目:服务器在读取文件的线程内执行从属(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变量?谢谢

1 个答案:

答案 0 :(得分:0)

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

public volatile String res=null;

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

但是你可能在这里有另一个问题,因为你有多个线程可能都在写'res'变量(取决于你的套接字有多活跃)。您可以在这里获得“丢失的更新”或其他“竞争条件”。所以也许你甚至需要一个synchronized。但是这里解释多线程太过分了。请谷歌了解一下。不幸的是,多线程并不是一件轻而易举的事情,你不能只是按照自己的意愿制作新的线程,并希望一切顺利。在大多数情况下,添加volatile是而不是解决方案。这可能只是你想在这里做的事情。