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

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

问题描述:

我有简单的调用线程哪些做简单的工作。当条件满足时
我想调用或通知基类(启动线程的那个)
工作完成。
这样做的最好方法是什么?Java如何在作业完成后调用或通知调用类?

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 run方法方法和更新ScheduledThreadsManager?

+0

http://www.javaworld.com/article/2077462/learn-java/java-tip- 10 - 执行回调 - 例程in-java.html首先命中“Java回调”:D – Fildor

+0

但是,你正在严重overcoding这一点。你可以用Executor和Futures做所有你想要的。参见'submit'。请注意,执行程序的关闭只能确保不能添加新的任务。 – Fildor

您可以通过界面实现它,例如,

interface SomethingToBeCalled{ 
void notfiy(); 
} 

你BaseClass的扩展了这个

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

,为你的任务建构这个接口

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

,现在您可以通知BaseClass的

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

请注意'notify()'将运行在单独的线程上。 – Fildor

+0

和这个BaseClass何时通知可以更新ScheduledThreadsManager 公共方法? – user63898

+0

@ user63898该类名称“BaseClass”实际上是您的真实类名“ScheduledThreadsManager”的替代品。所以你可以直接实现它。 –

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

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的专用方法,您的Task将不知情。

+0

did not understand this .. – user63898

+1

@ user63898我添加了一个例子,它有帮助吗? –

+0

呼叫类是什么结果? ,从什么时候java有“ - >”? – user63898

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

您可以提交一个RunnableExecutorService并取回一个Future

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

现在你可以调用future.get()(任选一超时),这将阻塞,直到未来完成:

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

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

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

番石榴扩展Future接口与ListenableFuture,它允许您执行Future完成后回调。 Java 8也增加了CompleteableFuture,但我仍然处于黑暗时代,所以我从来没有用过:) :)

+0

这很好,但OP可能不想阻止。如果他阻止,根本没有理由使用'ExecutorService'(假设没有并行性)。 –

+0

@JaroslawPawlak见编辑。 –

+2

除了Guava的'ListenableFuture',你可以使用Java 8的'CompletableFuture'。 – Jesper