尝试使用firepropertychange,propertychangesupport更改值

时间:2019-01-10 15:24:15

标签: java inotifypropertychanged

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

}

1 个答案:

答案 0 :(得分:1)

再次使用侦听器设计模式的主要目的是避免必须使用while循环来不断轮询状态变化,而是让侦听器和侦听器支持一起工作,以便在通知对象的状态改变。

其他问题:

  • Bean应该包含“监听”或“绑定”字段
  • bean本身应在状态更改的位置而不是其他任何类的位置调用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();