英文:
How to execute activate and deactivate methods of OSGI bundle in a single thread
问题
我有一个OSGI捆绑包,其结构如下:
//...
public ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
//...
@Activate
public void activate() {
executor.submit(new Runnable() {
@Override
public void run() {
//调用3个函数并记录数据
}
});
}
@Deactivate
public void deactivate(){
//调用另外2个函数
}
在activate
方法中的执行器(executor)确保以与所有其他捆绑包线程分离的方式调用3个函数,因为这些函数实际上实现了一些复杂的Windows消息循环,即一个while true循环。为了不阻塞其他捆绑包,它在单独的线程中激活。现在我遗憾地注意到,为了在deactivate
方法中运行2个函数,我需要在与在activate
方法中运行3个函数的相同线程中运行它们。简单地说,我需要确保我的捆绑包的activate
和deactivate
方法在同一个线程中运行,但仍然要保持此捆绑包激活在其他捆绑包之前以一个独立的线程中进行。
我的问题是:如何实现这一点?
我在Java并发方面不是专家,我尝试过在deactivate
方法中也调用这个执行器,但我不知道如何使用一个Runnable
任务来做到这一点,因为在deactivate
中我只需要调用2个函数,在activate
中只调用3个函数,并且不应进行其他调用。
更新:抱歉,我忘记提到在另一个捆绑包中有一个例程,在特定情况下会调用context.getBundle(0).stop()
,以便为所有捆绑包调用停用操作。如果我只想在deactivate
方法中添加与activate
方法中相同的提交例程,那么在这种情况下,我可以清楚地看到,在我的捆绑包的deactivate
方法中,提交体内的这两个函数未被调用。
英文:
I have an OSGI bundle of a following structure:
//...
public ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
//...
@Activate
public void activate() {
executor.submit(new Runnable() {
@Override
public void run() {
//call 3 functions and log the data
}
}
}
@Deactivate
public void deactivate(){
//call 2 other functions
}
The executor in the activate method makes sure that 3 functions are called in a separate from all other bundles thread, because those functions actually implement some sophisticated Windows-message-loop, i.e. a while true loop, that's why, in order not to block other bundles, it is activated in a separate thread. Now what I've sadly noticed, that in order to run 2 functions in deactivate method I need to run them in the same thread, in which 3 functions in activate method were run. Simply speaking, I need to be sure, that activate and deactivate methods of my bundle run in the one same thread, but still to keep this bundle activation separated (in an own thread) from the other bundles.
My question is: how to implement this?
I am not a guru in concurrency in Java, I've tried simply to call this executor in the deactivate method too but I don't know how to do it with one Runnable task, since in deactivate I have only to call 2 functions and in activate only 3 functions and no other calls should be made.
UPD: sorry, I forgot to mention, that there is a routine in another bundle, which calls in certain situations context.getBundle(0).stop()
in order to call a deactivation for all bundles. If I want just to add the same submit routine in the deactivate method as is in activate, then in such situation I could clearly see, that those 2 functions from deactivate method of my bundle in the submit's body were not called.
答案1
得分: 0
在“deactivate”中简单地再次执行“executor.submit”。由于它是单线程执行器,它将确保只有一个线程处理两者。
唯一的问题是如何可靠地关闭执行器。通常在“deactivate”之后,组件应该已关闭其所有资源。
英文:
Simply do another executor.submit in deactivate. As it is a single threaded executor it will make sure only one thread processes both.
The only question is how to shut down the executor reliably. Normally after deactivate a component should have closed all its resources.
答案2
得分: 0
这听起来是一个非常常见的问题。我会明确地指出你正在使用一个线程,并使用 Thread 中为此设计的方法。在 activate 中,你启动线程,在 deactivate 中,你中断它。你的主循环会监视中断状态,并在被中断后执行你的 deactivate 函数。在中断之后,最好加入线程,以确保你的 activate()
方法在后台线程完成运行 deactivate 函数之前不会返回。
由于退出框架(停止 bundle 0)必须停止所有 bundle,而停止的 bundle 将停用其组件,所以这应该能够正常工作。
public class Foo extends Thread {
@Activate
void activate() {
start();
}
@Deactivate
void deactivate() throws Exception {
interrupt();
join();
}
public void run() {
while (!isInterrupted()) {
try {
// ... 你的三个函数循环
} catch (InterruptedException e) {
break;
}
}
// ... 两个停用函数
}
}
英文:
This sounds like a very common problem. I would just make it explicit you're using a thread and use the methods in Thread that were designed for this. At activate you start the thread, at deactivate you interrupt it. Your main loop watches the interrupt status and executes your deactivate functions after it is interrupted. After interrupt, it is best to join the thread to ensure your activate()
method does not return before the background thread has finished running your deactivate functions.
Since exiting the framework (stopping bundle 0) must stop all bundles, and a stopped bundle will deactivate its components, this should all work.
public class Foo extends Thread {
@Activate void activate() { start(); }
@Deactivate void deactivate() throws Exception { interrupt(); join(); }
public void run() {
while(!isInterrupted()) try {
... your 3 function loop
} catch( InterruptedException e) {
break;
}
... 2 deactivate functions
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论