【问题标题】:Why is my count++ resetting in my run() method inside the Thread class?为什么我的 count++ 在 Thread 类中的 run() 方法中重置?
【发布时间】:2014-11-03 06:27:30
【问题描述】:

每当客户端与服务器建立连接时,客户端都会向服务器发送一个字符串消息“11”,当服务器收到字符串消息“11”时,它会运行count++。然后已经建立了两个连接,这应该使count++中的count = 2运行两次,但是当客户端连接时,我检查了它并且客户端正确地将字符串消息“11”发送到服务器,但计数保持为1并且从不进入 if(count == 2) 块。一直在测试和寻找几个小时,但似乎无法找到问题所在。请帮忙!谢谢

客户的sn-p代码:

Socket s = new Socket(hostname, port); // Plug in the socket to connect to the server
pw = new PrintWriter(s.getOutputStream()); //Instance of sending it out
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));

public void run() { //Deal with reading from server and print them out

    try {
        pw.println("11"); //Sends the message when connection is made to the server
        pw.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }

    try{

           while(true){ 

                 String line = br.readLine(); //Read in the message from server

                 if(line.equals("12")){ //When finally receives the string message "12" from   server

                     button.setBackground(Color.white);
                     button.addActionListener(sl);

                 }

                 int update = Integer.parseInt(line);

                 if(update < 10){
                     current-= update;
                 }
     }

    } catch (IOException ioe){
        System.out.println("ioe in ChatClient.run: " + ioe.getMessage());
    }
}

服务器线程的sn-p代码:

PrintWriter pw = new PrintWriter(s.getOutputStream());

public void run(){
    try{

        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));

        while(true){
            String line = br.readLine(); //blocking //Keep reading in messages

            if(line.equals("11")){ //Tested it out and does receive "11" whenever a client connects and prints out "11" 
                count++; //But the problem is count stays as 1 every time it connects and never becomes 2
                System.out.println(line);
                System.out.println(count);
            }

            if(count == 2){ //Never able to reach inside this block of code
                pw.println("12");
                pw.flush();
                count++;
            }
        }

    } catch(IOException ioe){
        System.out.println("ioe in ChatTHread: " + ioe.getMessage());
    }
}

编辑 - 服务器代码:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.Vector;

public class Server {

private int count = 0;
private Vector<FFThread> ctVector = new Vector<FFThread>(); //Parametrized

public Server(int port){

    try{

        ServerSocket ss = new ServerSocket(port); //Server socket to connect to the port

        while(true){

            Socket s = ss.accept();  // Listens for a connection to be made to this "s" socket and accepts it.


            FFThread ct = new FFThread(s, this); //Get new socket access thread
            ctVector.add(ct); //Appends the specified element "ct" to the end of this Vector.
            ct.start(); 
        }

    } catch(IOException ioe){
        System.out.println("ioe in ChatServer: " + ioe.getMessage());
    }
}

public int counter(){
    this.count = 0;
    count++;
    return count;
}

public void sendMessage(String message, FFThread ct){
    for(FFThread c : ctVector ){
        if(!c.equals(ct)){ //Two different clients
            c.sendMessage(message);
        }
    }
}

public void removeThread(FFThread ct){
    ctVector.remove(ct);
}

public static void main(String [] args){
    Scanner scan = new Scanner(System.in);
    System.out.print("What port? ");
    int port = scan.nextInt();
    new Server(port);
}

}

编辑 - 服务器的线程类:

import java.awt.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;


public class FFThread extends Thread {

private Socket s;
private Server cs;
private PrintWriter pw;
private int count = 0;
boolean ready = false;

public FFThread(Socket s, Server cs){

    this.s = s;
    this.cs = cs;

    try{

        this.pw = new PrintWriter(s.getOutputStream()); //Set up to send messages to clients

    } catch(IOException ioe){
        System.out.println("ioe in ChatThread constructor: " + ioe.getMessage());
    }
}

【问题讨论】:

  • 检查变量line的长度是否为2,因为比较可能总是假的,因此不会增加count。例如:“11”不等于“11”。
  • 尝试添加“else”块,看看你的假设是否正确。使用 IDE 进行调试也很有用。
  • @JoseLuis 这似乎不是问题,因为我用 System.out.println(line) 和 System.out.println(count) 对其进行了测试,它们被打印出来了行是字符串“11”,但计数始终保持为 1,证明他们能够进入 if 块。
  • @Jayan 您能否详细说明您在下面作为答案的意思?
  • 你能显示更多的服务器代码吗? count 的声明和初始化会很有帮助。

标签: java multithreading user-interface networking


【解决方案1】:

您的 Server 类为每个传入连接启动一个新线程(FFThread 的实例)。您的FFThreadrun 方法执行count++,但它必须在局部变量上执行,因为它没有访问Server 类中的count 变量。因此,每个线程将自己的count0 递增到1,并且永远不会达到两个。

您的 run 方法应递增(并测试)服务器实例的 count 变量,以使该计数达到 2。您必须以线程安全的方式递增它(即使用同步方法)。

我相信将以下内容添加到您的 Server 类中会起作用:

private volatile int count = 0;
...
public synchronized void incCount()
{
    count++;
}

public int getCount()
{
    return count;
}

然后,在您的 FFThread 类中,使用 this.cs.getCount()this.cs.incCount() 读取并增加计数。

【讨论】:

  • 你介意展示一下吗?我很迷茫......最方便的方法是什么?
  • 它适用于第二个启动的客户端,但对于第一个它没有。我猜第一个仍然保持计数为 1,但是一旦第二个客户端计数达到 2,服务器是否应该向两个客户端发送字符串“12”的消息?
  • @OM 否,因为每个服务器线程都将消息发送到单个客户端。服务于第一个客户端的第一个线程没有发送“12”,因为在计算时 count 不是 2。如果第一个客户端将向服务器发送额外的输入,则服务器线程的String line = br.readLine() 调用将停止阻塞,并且将再次到达检查计数并发送“12”的代码。
  • 使用volatilesynchronized 但不能同时使用两者,因为除了较慢的代码之外,它什么也没有。如果您只执行原子 get() 和 set() 操作,volatile 最有用,在这种情况下您不需要使用synchronized。由于递增不是原子的 - 它是 get() + set() - volatile 不适用。请参阅JLS section 8.3.1.4,以及AtomicIntegerFieldUpdater Javadoc
  • @Eran 那么当字符串达到“12”时,我应该如何让它向第一个客户端发送消息?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-27
相关资源
最近更新 更多