2015-11-10 34 views
2

我有簡單的調用線程哪些做簡單的工作。當條件滿足時
我想調用或通知基類(啓動線程的那個)
工作完成。
這樣做的最好方法是什麼?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

回答

1

您可以通過界面實現它,例如,

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」的替代品。所以你可以直接實現它。 –

3

我認爲最好的辦法是給任務的回調函數:

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

3

不要通知調用對象:使用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

相關問題