使用Java进行跨线程函数调用

时间:2011-12-20 05:46:25

标签: java multithreading function

我想知道如何在Java中调用跨线程的不同函数。现在,我正在这样做的方式是将我的线程的run()函数编写为

public volatile boolean invokeMyFunction = false;

public void run() {
    while(true) { 
        if(invokeMyFunction) {
            MyFunction();
            invokeMyFunction = false;
        }
    }
}

如果我想从该线程外部运行函数MyFunction(),则写入“whateverobject.invokeMyFunction = true”,它将在线程内运行我的函数,因为该循环将拾取它。这对我很有用,但它使用100%的CPU,因为它是(真)循环。我可以通过在循环中单独使用Thread.sleep(1000)来解决这个问题,但这看起来很混乱,我不禁要相信有更好的方法可以做到这一点。

4 个答案:

答案 0 :(得分:4)

我想在这里,实现这一目标的最简单和CPU友好的方法是

public void run() {
    while(true) { 
        synchronized(foo) {
            while(!invokeMyFunction) {
                foo.wait();
            }
        }
        MyFunction();
        invokeMyFunction = false;
    }
}

上面的代码在它自己的Thread中运行。另一个线程可以这样做让第一个Thread运行MyFunction():

invokeMyFunction = true;
foo.notifyAll();

请注意 a)你不能使invokeMyFunction成为布尔值并在其上进行同步,因为在所有java中只有两个布尔值:) b)如果invokeMyFunction设置了n次,如果invokeMyFunction设置为true而它不是false,它可能仍会运行更少次。 c)使用BlockingQueue可能更容易,并允许线程1运行任意函数:

while(true) {
    Runnable next = queue.take();
    next.run()
}

另一个线程会告诉它像这样运行MyFunction:

queue.put(new Runnable() {
    void run() {
        MyFunction();
    }
});

对我来说似乎更容易:)此外,如果您希望n个线程运行队列中的任何内容,您只需要生成侦听队列的n个线程。或者您可以学习如何使用线程池:http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

注意:

queue.put()阻塞,直到BlockingQueue中有新空间可用,即如果它是“满”则阻塞。请参阅您正在使用的任何BlockingQueue实现的实现文档,以查看您的队列是否有限制。在任何情况下,请确保您没有添加更多项目,而不是处理太久。

答案 1 :(得分:2)

您可以在线程中放置一个监视器,然后在该监视器上等待。当你调用这个函数时,告诉监视器释放一个人(它应该只有那个人)可以运行你的函数,然后再回去等待。

另一方面,睡眠路线也没有任何内在错误。我明白为什么你会把它称之为凌乱,但它犯了一个愚蠢错误的机会较低,并且提供了你服务之间更松散的耦合。

(旁注 - 你不需要在线程中放置一个监视器。你可以使用该对象作为监视器而不是内部监视器。但是你可以将自己打开给可能干扰它的其他人,所以它是最好使用私有内部对象作为监视器。)

答案 2 :(得分:2)

您的代码中有几个漏洞,除了您要占用CPU之外。

如果您的其他线程希望此线程在MyFunction执行所需的时间内调用两次,该怎么办?你最终会错过一次调用。

改进可能是:

public volatile boolean invokeMyFunction = false;

public void run() {
    while(true) { 
        if(invokeMyFunction) {
            // Moved here.
            invokeMyFunction = false;
            MyFunction();
        }
    }
}

但是,这只会降低竞争条件,而不是不可能。

您可能最好使用BlockingQueue,就像我建议here一样。让另一个线程在这个线程读取的队列中发布一些东西。你也不会那样占用cpu。

答案 3 :(得分:1)

你的计划对我来说很奇怪。为什么要开始一个线程,但要等到未来的某个未知时间才会被告知要运行?为什么不在以后开始呢?

编辑添加以澄清为glowcoder

编辑删除 - 我的不好,我误解了他的问题,他希望能够多次调用MyFunction。在这种情况下,他应该使用其他答案中建议的某种队列