如何用信号通知Android线程执行方法?

时间:2019-02-20 15:14:11

标签: java android multithreading

我想产生一个休眠的线程,然后在接收到信号时执行一个方法。方法完成后,线程应返回睡眠状态,等待下一个信号。

传入的信号足够频繁,以至于我不希望每次信号进入时都产生新线程的开销。目前,我正在轮询该信号,但我相信有更好的方法可以做到这一点。

我已经看到了使用Handler和AsyncTask的示例,但是我不确定最好的实现是什么。有什么建议吗?

public ModuleFeedbackTask extends Thread
{
    RadioModule radioModule;
    public ModuleFeedbackTask(RadioModule radioModule)
    {
        this.radioModule = radioModule;
    }

    @Override
    public void run()
    {
        //Previously just called the function
        //moduleUpdateTask();

        //Currently polling for an update
        //What I want to do is sleep until I get some signal
        while(mState == JOB_STATE_RUNNING)
        {
            //Poll module 
            moduleUpdateTask();

            //Sleep
            sleep(5);
        }
    }

    public moduleUpdateTask()
    {
        //Check if module is ready for processing
        if(radioModule.updateReady)
        {
            radioModule.updateReady = false; //Clear flag
            //do some intensive stuff
        }
    }
}


/**
 * Callback when a radio module reports new data
 * @param m Radio module with new data
 */
@Override
protected void onModuleStatusReport(RadioModule m)
{
    if(mState == JOB_STATE_RUNNING)
    {
        //The below comments spawn a new thread on each feedback... 
        //I want to get around this

        //ModuleFeedbackTask moduleFeedbackTask = new ModuleFeedbackTask(m);
        //moduleFeedbackTask.setPriority(Thread.NORM_PRIORITY);
        //moduleFeedbackTask.setName("ModFbTask");
        //moduleFeedbackTask.start();

        super.onModuleStatusReport(m);
    }
}

1 个答案:

答案 0 :(得分:3)

有很多方法可以解决此问题,但是我建议使用在工作线程与任何其他可以发出信号来执行任务的线程之间共享的BlockingQueue。工人的任务被设置为一个循环,在该循环的顶部,它尝试从队列中take()对象。这将阻塞,直到其他线程将一个对象排队,该对象构成了信号。

这种方法的一些优点包括:

  • 您可以轻松自然地一次将多个信号排队,这样,如果工人在张贴信号时实际上正在工作,该信号就不会丢失;

  • 您可以通过排队的对象将信息传达给工作人员,例如任务参数或退出而不执行任何任务的信号;

  • 您有一个内置选项,用于在接收信号时使用超时;和

  • 所有BlockingQueue实现都是线程安全的,因此您不必担心实现自己的同步。

示例

public OnDemandTask implements Runnable {
    private final BlockingQueue<?> signalQueue;

    public FeedbackTask(BlockingQueue<?> signalQueue) {
        this.signalQueue = signalQueue;
    }

    @Override
    public void run() {
        try {
            while (true) {
                // blocks until an object becomes available from the queue
                // may throw InterruptedException
                signalQueue.take();

                performTask();
            }
        } catch (InterruptedException ie) {
            // we've broken out of the loop; nothing further to do
        }
    }

    private performTask() {
        // ...
    }
}