【问题标题】:Edit a variable from a thread从线程编辑变量
【发布时间】:2018-04-08 19:53:28
【问题描述】:

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

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

}

当我执行这个 main 时,我在屏幕上什么也看不到。我知道这是因为服务器卡在了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 变量吗?谢谢

【问题讨论】:

  • 如果在t.start()之后添加;线 t.join();你可能会看到结果。但是你的应用程序将无非是同步的(加入只是等待直到线程结束,所以就像你将直接运行 run() 方法的内容)。所以我可以假设这不是你想要的——不是吗?

标签: java multithreading sockets


【解决方案1】:

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

public volatile String res=null;

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

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

【讨论】:

  • 我猜问题似乎出在while循环中。 main 卡在 Server.manage 方法中,因为它包含一个非停止循环。我将如何替换它,以便服务器在线程完成编辑 res 时停止 while 循环?
  • 对,我什至没有注意到一个大声笑。 (我谈到的另一个问题仍然存在,所以你一定要让它变得易变)。要等到启动的线程完成,只需在 t.start() 之后添加 t.join()。它将阻塞直到 t 完成,然后继续。当然你应该去掉while循环。或者,将 main 方法中的代码放入服务器的 run 方法中。老实说,我真的不明白你想在这里做什么,主线程打印该变量的目的是什么?
  • 嗯,主要目标是让 Server 类启动 ReaderF 线程来读取文件。然后,该线程应该将文件的内容发送回服务器。接下来,服务器应该执行一个池,让他将结果发送给每个尝试连接的客户端。我开始做第一部分,使线程读取文件并将其发送回服务器。在 main 上打印只是为了测试变量是否被编辑
猜你喜欢
  • 2015-06-28
  • 2016-09-21
  • 2017-08-08
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多