Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将更改通知正在运行的线程_Java_Multithreading_Design Patterns - Fatal编程技术网

Java 如何将更改通知正在运行的线程

Java 如何将更改通知正在运行的线程,java,multithreading,design-patterns,Java,Multithreading,Design Patterns,我正在处理一个客户机/服务器项目,它监视服务器中的系统事件,并向客户机发送更改通知。它由一个监视者对象和一个服务器对象组成,前者负责监视,后者为连接到它的每个客户端创建线程。考虑到下面的简化代码(我包括了所有必要的代码) 现在,问题是从mySrv对象接收到通知,并且mySrv的propertyChange被正确执行,并且disMsg被填充。但是,我不知道如何使用ClientHandler的run方法来执行notifyStatusChange()将更改发送给客户端。我试着连接线程和许多不同的东西,

我正在处理一个客户机/服务器项目,它监视服务器中的系统事件,并向客户机发送更改通知。它由一个监视者对象和一个服务器对象组成,前者负责监视,后者为连接到它的每个客户端创建线程。考虑到下面的简化代码(我包括了所有必要的代码)

现在,问题是从
mySrv
对象接收到通知,并且
mySrv
propertyChange
被正确执行,并且
disMsg
被填充。但是,我不知道如何使用
ClientHandler
run
方法来执行
notifyStatusChange()
将更改发送给客户端。我试着连接线程和许多不同的东西,但没有一个奏效。如果有人知道一个更好的方法,或者向我指出我的错误和最佳实践,或者具体告诉我如何实现这一点,我将不胜感激

谢谢


一种常见的模式是生产者消费者。线程可以共享一个
BlockingQueue
[1],其中生产者线程添加项目,消费者线程从集合中获取项目

有很多实现的例子

[1]

您的“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();
}}

我可以在这里看到一些不同的问题

服务器似乎在等待来自客户端的连接,并在收到连接时创建并启动
ClientHandler
线程。一旦接收到这样的连接,它的
run
方法将在自己的线程中执行

因此,此时我们有两个线程,服务器线程和客户端线程,但是如果客户端在连接后没有向套接字写入任何内容,那么线程将在
clientMessage=reader.readLine()处阻塞。

现在让我们假设在主线程中调用了
propertyChange
,它将
isChanged
设置为
true
。如果我理解正确,您希望调用
notifyStatusChange
。但也存在一些问题:

  • ischange
    变为
    true时,
    ClientHandler.run
    可能会被阻止从客户端连接读取

  • 即使从套接字读取了某些内容,线程也可能会发现
    isChanged
    为false。这是因为更改发生在不同的线程中。如果变量被声明为
    易失性
    ,则不会发生这种情况

  • 服务器接受多个连接,每个连接使用不同的线程。但是每个线程的run方法都可以将
    isChanged
    设置为
    false
    ,因此即使该值传播到所有线程,也只有一个线程会打印通知


  • 我知道这不是完整的答案,但你需要解决这些问题

    你看了吗?
    ischange
    定义在哪里?你让它变得不稳定了吗?(我不是说这是问题所在;我只是试图理解代码。)@ElliottFrisch,
    PropertyChangeListener
    的使用已经实现了观察者/可观察设计模式,而且我接收观察者对象的通知也没有问题;但是,我无法将更改发送到
    ClientHandler
    run
    方法。@ajb:
    isChange
    在构造函数中定义,并且当从
    观察者
    对象收到通知时,也会更改为
    true
    。正如我前面提到的,我收到了通知,但是没有执行
    ClientHandler
    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();
    }}