【问题标题】:How notify second thread of variable's change如何通知第二个线程变量的变化
【发布时间】:2017-04-18 17:43:59
【问题描述】:

我有两个线程。第一个更改变量 Data 的值。如果其值已更改,则第二个打印该值。我试图做第二个线程,每次变量的值发生变化时打印,但我没有成功。有人可以帮助我吗?

线程 1

 class someservice{

     volatile int data;
     Boolean Flag = false;

     public void mymethod(){

         flag = true;

         for (Integer i = 1; i < sheet.getRows(); i++) {

             data = someMethod();  //this method when called return a new 
                                   //value  
         }

         flag = false;
         ...
     }
  }

线程 2

 Promise p = task {
            try {

                while (true) {

                    if (engineService.getFlag()) {

                            print(someservice.data);                              

                    }else{
                        break;
                    }
                }
            } catch(Throwable t) {
                ...
            }
        }

【问题讨论】:

  • 您在更改变量时是否将engineService.getFlag() 设置为true?我在您的代码中没有看到它...
  • 你走在正确的轨道上......而不是承诺使用可调用的,未来......

标签: java multithreading observable


【解决方案1】:

既然你提到了 Promises,我推断你对 +C++11

中的 future/promise 很熟悉

在 java 中也有类似的方法,未来可调用...

public class HW5 {
    public static void main(String[] argv) throws InterruptedException, ExecutionException {
    FutureTask<Boolean> myFutureTask = new FutureTask<>(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
        // implement the logic here and return true if everything was
        // ok, false otherwise.
        Thread.sleep(5000);
        System.out.println("dddd");
        return System.currentTimeMillis() % 2 == 0;
        }
    });

    ExecutorService executor = Executors.newFixedThreadPool(1);
    executor.execute(myFutureTask);
    Boolean result = myFutureTask.get();
    System.out.println("Done!");
    }
}

FutureTask 在一个接受一个可调用对象的类中,该可调用对象在其工作完成后可以返回一个对象......为了执行 Future 任务,您可以使用 Executor 服务,特别是调用方法执行,因为您需要等待那么执行这项工作的线程是必要的,你调用 Future.get,这基本上会阻塞主线程,直到未来完成,为了验证结果,只需读取变量 result..

【讨论】:

    【解决方案2】:

    您可以在线程中使用 notify() 和 notifyAll() 方法。看看这个链接:https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

    public synchronized void guardedJoy() {
        // This guard only loops once for each special event, which may not
        // be the event we're waiting for.
        while(!joy) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        System.out.println("Joy and efficiency have been achieved!");
    }
    
    
    public synchronized notifyJoy() {
        joy = true;
        notifyAll();
    }
    

    【讨论】:

    • 不要写一个空的 catch 块。并且不要忽略 InterruptedException;中断是来自另一个线程的显式请求,用于停止您正在执行的操作并正常退出。忽略它会使您的代码成为流氓线程。
    • 同意。这是我引用的 Oracle 链接中的一个 sn-p。我认为他/她不会逐字使用代码。 :)
    • 谢谢 前面的答案已经解决了。谢谢!
    【解决方案3】:

    你必须查找更多关于并发编程的数据,我现在可以告诉你一些基础知识,嗯,不是那么基础,但我会尽力而为:

    在这里,你有一个监视器,它是一个抽象概念,在简历中,监视器是一个 类与它的一切 使用“同步”的方法 作为修饰语,它意味着, 只有 一根线 可以访问 方法 一次。所以, 在里面 监视器是 变量 你 想打印, 和“旗帜”, 告诉你如果 变量 被修改了。最后, 你可以 见 最重要的是,“wait()”和“notify()”方法, 那些方法 停止线程,或“播放” 又来了。

    你问 在这里

    printValue()方法,如果你的变量改变了,如果变量没有改变,用wait()方法让thead休眠,当其他的时候

    执行changeValue()方法,修改值,调用notify()方法,唤醒线程,所以,做这一切,可以保证三件事:

    安全:意味着线程会做你想做的事 没有死锁:意味着被置于睡眠状态的线程将来会被唤醒。 互斥:意味着只有一个线程在执行关键代码,例如操作。 “++”不是原子的,是在一个action里面细分,创建一个局部var,读取var,sum,asign,所以,如果游戏中有多个线程,值可能不连续,示例:

    i = 0;
    i ++;
    output: 1;
    output: 2;
    output: 3;
    output: 5;
    output: 4;
    output: 7;
    

    这可能会发生,即便如此,这也会发生在下一个代码中,因为执行的线程不止一个。嗯,这就是多线程编程的方式,或多或少

        public class Monitor {
    
            private int value = 0;
            public static boolean valueHasChanged = false;
    
            public synchronized int changeValue(int newValue){
                this.value = newValue;
                Monitor.valueHasChanged = true;
                this.notify();
                return this.value + 1;
            }
    
            public synchronized void printValue(){
                while(!Monitor.valueHasChanged){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println(this.value);
                Monitor.valueHasChanged = false;
            }
    
            public static void main(String[] args) {
                Monitor ac = new Monitor();
    
                BClass t1 = new BClass(ac);
                AClass t2 = new AClass(ac);
    
                t1.start();
                t2.start();
            }
    
            public int getValue() {
                return this.value;
            }
        }
    

    现在是线程:

        public class AClass extends Thread{
    
            private Monitor ac;
    
            public AClass(Monitor ac) {
                this.ac = ac;
            }
    
            @Override
            public void run() {
                while(true){
                    this.ac.printValue();
                }
            }
    
        }
    

    最后:

        public class BClass extends Thread{
    
            private Monitor ac;
    
            public BClass(Monitor ac) {
                this.ac = ac;
            }
    
            @Override
            public void run() {
                int v = 0;
                while(true){
                    this.ac.changeValue(v);
                    v++; // this sum is not secure, if you want to print an 
                         // ascending order, the code is diferent, I will show in
                         // above.
                }
            }
    

    现在,如果您想要有序打印:

    监视器将如下所示:

        public class Monitor {
    
            private int value = 0;
            public boolean valueHasChanged = false;
            private boolean hasPrint = true;
    
            public synchronized void changeValue(int newValue) {
                this.value = newValue;
                this.valueHasChanged = true;
                this.notify();
            }
    
            public synchronized void changeValuePlusOne() {
                while (!hasPrint) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                this.value++;
                this.valueHasChanged = true;
                this.hasPrint = false;
                this.notifyAll();
            }
    
            public synchronized void printValue() {
                while (!this.valueHasChanged) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(this.value);
    
                this.valueHasChanged = false;
                this.hasPrint = true;
                this.notifyAll();
            }
    
            public static void main(String[] args) {
                Monitor ac = new Monitor();
    
                BClass t1 = new BClass(ac);
                AClass t2 = new AClass(ac);
    
                t1.start();
                t2.start();
            }
    
            public int getValue() {
                return this.value;
            }
    
        }
    

    还有线程:

        public class BClass extends Thread{
    
            private Monitor ac;
    
            public BClass(Monitor ac) {
                this.ac = ac;
            }
    
            @Override
            public void run() {
                while(true){
                    this.ac.changeValuePlusOne();
                }
            }
    
            }
    

    另一个线程看起来等于:

    public class AClass extends Thread{
    
        private Monitor ac;
    
        public AClass(Monitor ac) {
            this.ac = ac;
        }
    
        @Override
        public void run() {
            while(true){
                this.ac.printValue();
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 2021-10-25
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      相关资源
      最近更新 更多