Java: 线程间共享和调用变量
Java: Sharing and calling variables between threads
我使用套接字制作了一个基本服务器,并想添加一个简单的 GUI 来打开和关闭它。为了使 GUI 在服务器处于 运行 while 循环时仍然工作,我为套接字创建了一个线程。现在我想的是向 while 循环添加一个布尔值,它退出所述循环并导致服务器在按下 GUI 中的按钮时停止。
现在的问题是布尔值是在GUI线程中设置的,需要在服务器线程中调用。我阅读了有关将布尔值设置为 volatile 或使用 AtomicBoolean 的信息,但它们似乎都不起作用。从服务器线程调用布尔值时,我可能需要寻找一些特别的东西吗?
这是我到目前为止编写的(简化的)代码:
public class GUI {
private static int port = 12345;
private static volatile boolean online = false;
public static void main(String[] args) {
//GUI works so i left the code out
//Basically generates a button giving it the actionlistener below
}
private static ActionListener getActionListener() {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(!online) {
online = true;
Thread serverThread = new Thread(new ServerThread());
serverThread.start();
} else {
online = false;
}
}
};
}
public static boolean getOnlineState() {
return online;
}
public static int getPort() {
return port;
}
}
和包含服务器线程的 class:
public class ServerThread implements Runnable {
@Override
public void run() {
try {
ServerSocket serSoc = new ServerSocket(GUI.getPort());
Socket cliSoc = serSoc.accept();
PrintWriter out = new PrintWriter(cliSoc.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(cliSoc.getInputStream()));
String input;
while(GUI.getOnlineState()) {
while((input = in.readLine()) != null) {
out.println(input);
}
}
out.println("Stopping");
cliSoc.shutdownInput();
cliSoc.shutdownOutput();
cliSoc.close();
serSoc.close();
out.close();
in.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
由于我是所有这些多线程的新手,所以可能还有其他一些错误,如果您能告诉我,我会很高兴。
嵌套循环有问题:
while(GUI.getOnlineState()) {
while((input = in.readLine()) != null) {
out.println(input);
}
}
一旦进入内循环,就会一直循环下去,直到输入流不工作,你将无法跳出。也许更好的方法是完全摆脱外部循环并结合您的逻辑:
while(GUI.getOnlineState() && (input = in.readLine()) != null) {
out.println(input);
}
其他不相关的问题是您对静态字段和方法的过度依赖,这可能适用于小型玩具程序,但随着您的程序变得更大并且可能有更多错误,这可能会增加问题。静态可能会增加不应连接的事物的连接性,增加代码的圈复杂度,从而增加错误的风险。将您的关注点隔离到私有实例字段和所需的最少 public 方法中。
我使用套接字制作了一个基本服务器,并想添加一个简单的 GUI 来打开和关闭它。为了使 GUI 在服务器处于 运行 while 循环时仍然工作,我为套接字创建了一个线程。现在我想的是向 while 循环添加一个布尔值,它退出所述循环并导致服务器在按下 GUI 中的按钮时停止。
现在的问题是布尔值是在GUI线程中设置的,需要在服务器线程中调用。我阅读了有关将布尔值设置为 volatile 或使用 AtomicBoolean 的信息,但它们似乎都不起作用。从服务器线程调用布尔值时,我可能需要寻找一些特别的东西吗?
这是我到目前为止编写的(简化的)代码:
public class GUI {
private static int port = 12345;
private static volatile boolean online = false;
public static void main(String[] args) {
//GUI works so i left the code out
//Basically generates a button giving it the actionlistener below
}
private static ActionListener getActionListener() {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(!online) {
online = true;
Thread serverThread = new Thread(new ServerThread());
serverThread.start();
} else {
online = false;
}
}
};
}
public static boolean getOnlineState() {
return online;
}
public static int getPort() {
return port;
}
}
和包含服务器线程的 class:
public class ServerThread implements Runnable {
@Override
public void run() {
try {
ServerSocket serSoc = new ServerSocket(GUI.getPort());
Socket cliSoc = serSoc.accept();
PrintWriter out = new PrintWriter(cliSoc.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(cliSoc.getInputStream()));
String input;
while(GUI.getOnlineState()) {
while((input = in.readLine()) != null) {
out.println(input);
}
}
out.println("Stopping");
cliSoc.shutdownInput();
cliSoc.shutdownOutput();
cliSoc.close();
serSoc.close();
out.close();
in.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
由于我是所有这些多线程的新手,所以可能还有其他一些错误,如果您能告诉我,我会很高兴。
嵌套循环有问题:
while(GUI.getOnlineState()) {
while((input = in.readLine()) != null) {
out.println(input);
}
}
一旦进入内循环,就会一直循环下去,直到输入流不工作,你将无法跳出。也许更好的方法是完全摆脱外部循环并结合您的逻辑:
while(GUI.getOnlineState() && (input = in.readLine()) != null) {
out.println(input);
}
其他不相关的问题是您对静态字段和方法的过度依赖,这可能适用于小型玩具程序,但随着您的程序变得更大并且可能有更多错误,这可能会增加问题。静态可能会增加不应连接的事物的连接性,增加代码的圈复杂度,从而增加错误的风险。将您的关注点隔离到私有实例字段和所需的最少 public 方法中。