Java:通过以某种方式从另一个线程

时间:2015-09-02 03:11:26

标签: java multithreading concurrency

我有一个包含2个主题的应用程序( main 和另一个主题 t1 ),它共享一个易变量 {{ 1}} 即可。有关如何通过myVar以某种方式发出信号,让main主题调用方法 myMethod 的任何想法? 我通过使用ChangeListener实现它,当myVar更改时调用myMethod,但是从 t1 调用方法,而不是从主线程调用(注意:我需要从主线程调用此方法,因为这是从Java调用JavaScript代码,因此出于安全原因,只有主线程可以这样做)。提前致谢。

4 个答案:

答案 0 :(得分:1)

你必须让你的主线程在某个标量的循环中旋转,我会推荐一个java提供的Atomics(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html),但你可以使用volatile,如果你想的话我认为。

每个线程只能按顺序运行 - 它只是计算的工作方式。处理这个问题的方法是,当主线程在某种循环中旋转时,你最终会检查是否已经设置了你的这个标量,当它有,你想要取消设置变量并执行你的JavaScript。在这段特殊的代码中,我认为使用compareAndSet操作时,Atomics优于volatile,因为如果你试图在一个操作中检查值然后设置volatile,那么使用volatile会让你在线程之间陷入困境。它又在另一个操作中给了另一个线程足够的时间再次设置它 - 这意味着你可能会错过对JS的调用,因为另一个线程在主线程检查它并设置它之间设置变量(尽管使用volatile和Atomics)可能会被解释为我的观点。)

//main thread
AtomicBoolean foo = new AtomicBoolean(false);
while (...somecondition...){
  if(foo.compareAndSet(true, false)){
    //execute JS
  }
  //do some other work
}

在T1线程中,只需拨打foo.set(true)

如果你希望main为你的JS调用每个时间T1将foo设置为true,那么你必须在T1中阻塞,直到main取消设置foo,或者使用{{ 1}}计算T1设置foo的次数 - 取决于您的需要。

答案 1 :(得分:0)

由于两者都共享同一个myVar实例,因此可以使两个线程同步共享变量。在执行main之前让myVar等待myMethod通知。稍后,t1可以通过变量myVar进行通知,等待的线程可以继续并继续进行方法调用。

以下代码段充分展示了这个想法

public class MainPlay {

    public static void main(String[] args) {
        MainPlay mp = new MainPlay();
        mp.execute();
    }

    public void execute() {
        Thread main = new Thread(mainRunnable, "main");
        Thread t1 = new Thread(t1Runnable, "t1");
        main.start();
        t1.start();
    }

    public Object myVar = new Object();

    public void myMethod() {
        System.out.println("MyMethodInfoked.");
    }

    public Runnable t1Runnable = new Runnable() {
        public void run() {
            synchronized(myVar) {
                try {
                    System.out.println("[t1] sleep for 1 sec");
                    Thread.sleep(1000);
                    System.out.println("[t1] Notifying myVar so Main can invoke myMethod");
                    myVar.notify();
                } catch (InterruptedException e) {
                    // interupted.
                }
            }   
        }
    };

    public Runnable mainRunnable = new Runnable() {
        public void run() {
            synchronized(myVar) {
                try {
                    System.out.println("[main] Waiting for t1 to notify...");
                    myVar.wait();
                } catch (InterruptedException e) {
                    // interrupted.
                }
                System.out.println("[main] executing main method");
                myMethod();
            }
        }
    };

}

输出

[main] Waiting for t1 to notify...
[t1] sleep for 1 sec
[t1] Notifying sharedObject so Main can invoke myMethod
[main] executing main method
MyMethodInfoked.

答案 2 :(得分:0)

您可以使用wait / notify块来阻止主线程继续,直到发出信号为止。

static Main main = // ...
static boolean signal = false;

// t1:
// Do work
signal = true;
synchronized (main) {
    main.notify();
}

// main:
synchronized (main) {
    while (!signal) {
        main.wait();
    }
}

myMethod();

答案 3 :(得分:0)

如果主线程没有别的办法,@ searchengine27提出的方法会导致该线程产生不必要的处理器负载。

因此,与一些AtomicXXX类相比,最好使用一些blocking queues,它允许从一个线程(带put())写入数据并消耗该数据另一个。如果这样的队列为空而不使用任何CPU资源,主队列将阻塞(通过调用take()方法)。