我使用propertychangesupport,propertychange和fireproperty change编写Java程序,现在可以正常工作,但无论如何,当ii更改值并将其打印出来时,但我尝试在监听的spesipic类上执行while循环时更改它只是在将它置于while条件时会退出循环,
公共类主要{
public static void main(String[] args) {
CLI cli = new CLI(System.in,System.out);
Server server = new Server(34567);
cli.addPropertyChangeListener(server);
new Thread(cli).start();
}
}
公共类CLI实现Runnable {
private Scanner scanner;
private String userInput;
private PropertyChangeSupport pcs;
private Boolean serverIsRunning;
public CLI(InputStream in, OutputStream out){
this.scanner = new Scanner(in);
pcs = new PropertyChangeSupport(this);
serverIsRunning = false;
}
@Override
public void run() {
while (true) {
System.out.println("pls enter your command:");
userInput = scanner.nextLine().trim().toUpperCase();
switch (userInput) {
case "START":
if (!serverIsRunning) {
pcs.firePropertyChange(userInput, null, "START");
new Thread(new Server(34567)).start();
serverIsRunning = true;
} else {
System.out.println("server is already running");
}
break;
case "SHUTDOWN":
if (serverIsRunning) {
pcs.firePropertyChange(userInput, null, "SHUTDOWN");
serverIsRunning = false;
} else {
System.out.println("server is not running");
}
break;
}
}
}
public void addPropertyChangeListener(PropertyChangeListener pcl){
this.pcs.addPropertyChangeListener(pcl);
}
public void removePropertyChangeListener(PropertyChangeListener pcl){
this.pcs.removePropertyChangeListener(pcl);
}
}
公共类服务器实现Runnable,PropertyChangeListener {
private int port;
private ServerSocket server;
private String userInput = "";
private Boolean serverIsRunning;
public Server(int port) {
this.port = port;
serverIsRunning = true;
}
public void propertyChange(PropertyChangeEvent evt) {
userInput = evt.getNewValue().toString();
switch (userInput) {
case "START":
System.out.println("Starting server...");
serverIsRunning = true;
break;
case "SHUTDOWN":
serverIsRunning = false;
break;
}
}
@Override
public void run() {
try {
server = new ServerSocket(port);
} catch (IOException e) { }
while (serverIsRunning) {
try {
new Thread(new Client(server.accept())).start();
} catch (IOException e) { }
}
try {
server.close();
System.out.println("shutdown");
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:1)
再次使用侦听器设计模式的主要目的是避免必须使用while循环来不断轮询状态变化,而是让侦听器和侦听器支持一起工作,以便在通知对象的状态改变。
其他问题:
fireXxx
方法。while (true)
循环。它应该做的就是监听并响应Bean中的状态更改,仅此而已。例如,假设您的bean看起来像这样:
public class Bean2 {
// constant for the property change name
public static final String STATE = "state";
private PropertyChangeSupport pcs;
// this is the "bound" field
private String state = "";
public Bean2() {
pcs = new PropertyChangeSupport(this);
}
public String getState() {
return state;
}
// notify listeners within the setter
public void setState(String state) {
String oldValue = this.state;
String newValue = state;
this.state = state;
pcs.firePropertyChange(STATE, oldValue, newValue);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
pcs.addPropertyChangeListener(propertyName, listener);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
// method to remove...
}
那么您的听众可能就这么简单:
public class Listener2 implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("From listener: state change -- new state: " + evt.getNewValue());
// this code will obviously need to do more...
}
}
并按如下方式使用:
public static void main(String[] args) {
Bean2 bean = new Bean2();
Listener2 listener = new Listener2();
bean.addPropertyChangeListener(Bean2.STATE, listener);
Scanner scanner = new Scanner(System.in);
String text = "";
while (!text.equalsIgnoreCase(EXIT)) {
System.out.print("Enter text or \"EXIT\" to quit: ");
text = scanner.nextLine();
if (!text.equalsIgnoreCase(EXIT)) {
bean.setState(text);
}
}
scanner.close();
}
看到,没有while循环,没有从bean中调用fireXxx
关于您的修改,我仍然不确定100%整个程序的设置,但也许可以确定以下几点:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class MyServer2 {
private static final String EXIT = "exit";
public static final int PORT = 4444;
private ServerSocket server;
public MyServer2() throws IOException {
server = new ServerSocket(PORT);
}
public void beanChanged(String text) {
// *** not sure what you want to do with this text
// *** other than to check that it != EXIT
if (!text.equalsIgnoreCase(EXIT)) {
try {
new Thread(new Client(server.accept()));
} catch (IOException e) {
e.printStackTrace();
}
} else {
// System.exit(0); // ????
}
}
public static void main(String[] args) {
MyServer2 server = null;
try {
server = new MyServer2();
} catch (IOException e) {
e.printStackTrace();
}
Bean2 bean = new Bean2();
Listener2 listener = new Listener2(server);
bean.addPropertyChangeListener(Bean2.STATE, listener);
Scanner scanner = new Scanner(System.in);
String text = "";
while (!text.equalsIgnoreCase(EXIT)) {
System.out.print("Enter text or \"EXIT\" to quit: ");
text = scanner.nextLine();
if (!text.equalsIgnoreCase(EXIT)) {
bean.setState(text);
}
}
scanner.close();
}
}
public class Bean2 {
// constant for the property change name
public static final String STATE = "state";
private PropertyChangeSupport pcs;
// this is the "bound" field
private String state = "";
public Bean2() {
pcs = new PropertyChangeSupport(this);
}
public String getState() {
return state;
}
// notify listeners within the setter
public void setState(String state) {
String oldValue = this.state;
String newValue = state;
this.state = state;
pcs.firePropertyChange(STATE, oldValue, newValue);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
pcs.addPropertyChangeListener(propertyName, listener);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
// method to remove...
}
public class Listener2 implements PropertyChangeListener {
private MyServer2 myServer2;
public Listener2(MyServer2 myServer2) {
this.myServer2 = myServer2;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
// notify server by calling its public method with new value
myServer2.beanChanged((String) evt.getNewValue());
}
}
public class Client implements Runnable {
private Socket socket;
public Client(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// TODO finish coding
}
}
但这仍然让人感到尴尬。请注意,由于它会阻塞代码,因此通常会将我的代码放入accept()
自己线程中的新客户端中,例如:
new Thread(() -> {
while (true) {
try {
new Thread(new Client(server.accept()));
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();