Java如何在作业完成后调用或通知调用类?

时间:2015-11-10 11:50:06

标签: java multithreading

我有一个简单的调用线程,它做了简单的工作。当条件满足时 我想调用或通知基类(启动线程的那个)
工作完成了。
做这个的最好方式是什么 ?

class TaskThread implements Runnable 
{

    private int result = -1;
    public TaskThread()
    {

    }    
    //must be thread safe
    public synchronized int getResult()
    {
        return result;
    }

    @Override
    public void run() {

        if(result==-1 || result < 0)
        {
            StartFoo();
            result  = InvokeAPI();
            if(result == 1)
            {
            // HERE i like to do something to notify the outside world that the job is done ...  
            }

        }
    }
}


//Base class 
public class ScheduledThreadsManager {

    private static ScheduledThreadsManager instance = null;
    private ScheduledExecutorService scheduler;
    private Runnable pTaskThread = null ;
    protected  ScheduledThreadsManager() 
    {

    }

    //must be set only once in the app life cycle
    public void Init(int corePoolSize,
                       long TimeUnitINSeconds)
    {
            pTaskThread = new TaskThread();
            scheduler = Executors.newSingleThreadScheduledExecutor();
            scheduler.scheduleAtFixedRate(pTaskThread,1,TimeUnitINSeconds,TimeUnit.SECONDS);
    }
    public int getResult()
    {
        return pTaskThread.;
    }
    // Runtime initialization
    // By defualt ThreadSafe
    public static ScheduledThreadsManager getInstance() {
        if(instance == null){
            synchronized (ScheduledThreadsManager.class) {
                if(instance == null){
                    instance = new ScheduledThreadsManager();
                }
            }
        }
        return instance;
    }


    public void ShutdownNow()
    {

        pTaskThread = null ;
        scheduler.shutdown();
    }
}

现在这就是我所说的:

//somewhere in the code 

ScheduledThreadsManager.getInstance().init(1,10);
int runThis = true;
while(runThis)
{
    int ifOne = ScheduledThreadsManager.getInstance().getResult()
    if(ifOne==1)
    {
        runThis = false;
        ScheduledThreadsManager.getInstance().ShutdownNow()
    }
}

我不确定是最好的方法,我能以某种方式从TaskThread运行方法并更新ScheduledThreadsManager吗?

3 个答案:

答案 0 :(得分:3)

我认为最好的方法是给任务一个回调函数:

<%= form_for :trip, url: {action: "index"}, html: {method: "get"} do |f| %>
  <%= f.select :country_obj_id, options_for_select(@countries.collect { |country|
    [country.name.titleize, country.id] }, @countries.first.name), {}, { id: 'countries_select', class: "form-control" } %>
  <%= f.select :city_obj_id, options_for_select(@cities.collect { |city|
    [city.name.titleize, city.id] }, 0), {}, { id: 'cities_select', class: "form-control" } %>
  <%= f.submit "Go!" %>
<% end %>

然后在您的任务中,最后添加Runnable callback = () -> System.out.println("done!"); 。或者,如果您的任务返回了您需要使用的值,请使用callback.run();代替Consumer

这是一个有效的例子:

Runnable

这允许您例如调用public class Task implements Runnable { private final Consumer<String> callback; public Task(Consumer<String> callback) { this.callback = callback; } @Override public void run() { // do actual work here instead String result = new Random().nextInt(2) == 0 ? "a" : "b"; // call a private method in Caller callback.accept(result); } } public class Caller { public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); executorService.submit(new Task((result) -> print(1, result))); executorService.submit(new Task((result) -> print(2, result))); executorService.submit(new Task((result) -> print(3, result))); Thread.sleep(2000); } private static void print(int id, String result) { System.out.println("task " + id + " done, returned: " + result); } } 的私有方法,您的Caller将对此一无所知。

答案 1 :(得分:3)

不要通知调用对象:使用ExecutorServiceFuture

您可以向Runnable提交ExecutorService并返回Future

Future<?> future = executorService.submit(myRunnable);

现在你可以调用future.get()(可选择暂停),这将阻止直到Future完成:

future.get();
future.get(5, TimeUnit.MINUTES);

这意味着您不需要引入任何新的回调接口或类似接口。您也无需立即致电future.get():您可以提交一大堆任务,然后再致电get

请注意,如果您向Callable<T>提交ExecutorService,则会返回Future<T>:如果您希望长时间运行的计算返回值,这将非常有用。

Guava使用ListenableFuture扩展Future接口,允许您在Future完成后执行回调。 Java 8还增加了CompleteableFuture,但我还处于黑暗时代,所以我从未使用过它:)

答案 2 :(得分:1)

你可以通过一个界面来实现它,例如

interface SomethingToBeCalled{
void notfiy();
}

你的BaseClass扩展了这个

ScheduledThreadsManager implements SomethingToBeCalled{
void notify() {...};
}

你给你的Task Constructor这个接口

public TaskThread(SomethingToBeCalled smth)
    {
      this.smth = smth;
    }

现在您可以通知BaseClass

 if(result == 1)
  {
  smth.notify();
  }