我正在开发一个客户端/服务器项目,该项目在服务器中监视系统事件并向客户端发送通知更改。它由一个观察的Watcher对象和为每个连接它的客户创建线程的服务器对象组成。考虑下面的简化代码(我包括了所有必要的代码)
现在,问题是从mySrv
对象收到通知,propertyChange
的{{1}}已正确执行,并且mySrv
已填充。但是,我不知道如何使用disMsg
run
方法来执行ClientHandler
以将更改发送给客户端。我尝试加入线程和许多不同的东西但没有工作。如果有人知道更好的方法或者指出我的错误和最佳实践,我会非常感激,或者向我展示如何实现这一目标。
谢谢,
notifyStatusChange()
答案 0 :(得分:2)
我可以在这里看到一些不同的问题。
服务器似乎等待来自客户端的连接,并在收到连接时创建并启动ClientHandler
线程。一旦收到这样的连接,它的run
方法将在其自己的线程中执行。
所以此时我们有两个线程,即服务器线程和客户端线程,但是如果客户端在连接后没有向套接字写入任何东西,则线程将在clientMessage = reader.readLine())
现在让我们假设在主线程中调用propertyChange
,并将isChanged
设置为true
。如果我理解正确,你期待被叫notifyStatusChange
。但是有一些问题:
ClientHandler.run
变为isChanged
时, true
可能会被阻止从客户端连接读取
即使从套接字读取了某些内容,该线程也可能会发现isChanged
为false。这是因为更改发生在不同的线程中。如果变量声明为volatile
,则不会发生这种情况。
服务器接受多个连接,每个连接使用不同的线程。但是每个线程的run方法可以将isChanged
设置为false
,因此即使该值传播到所有线程,也只有其中一个会打印通知。
我知道这不是完整的答案,但你需要解决这些问题。
答案 1 :(得分:1)
常见的模式是producer-consumer
。线程可以共享BlockingQueue
[1],其中生产者线程添加项目,而消费者线程从集合中获取它。
有很多实现的例子。
[1] http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
答案 2 :(得分:0)
你的“propertyChange()”是否被执行,如果是这样,你的代码应该没有任何问题。 无需再次执行“run()”或连接线程。
如果您只想通知正在运行的线程更改,以下简单代码将起作用。
package indika.java.core.network;
public class MyServer{
public boolean isChanged = false;
private String dispMsg;
public MyServer() throws InterruptedException {
Thread mthread = new Thread(new ClientThread());
mthread.start();
Thread.sleep(1000);
isChanged = true;
}
public class ClientThread implements Runnable {
public void run() {
boolean ok = true;
while (ok) {
System.out.println("Started thread!!!!");
if (isChanged) {
System.out.println("Server1: " + dispMsg);
notifyStatusChange();
isChanged = false;
ok = false;
}
}
}
}
public void notifyStatusChange() {
System.out.println("notifyStatusChange -- ");
}
public static void main(String[] args) throws InterruptedException {
new MyServer();
}}