假設現在你有兩個類別, 分別是A類別跟B類別,
A類別有一個很久的任務在執行,
B類別則是必須等A類別執行完畢以後, 再執行自己的任務
這時候有幾種方法可以解決這樣的情況:
- B不斷的去問A做完了嗎?
- 把B排在A的後面直到A做完
- 當A做完了透過機制告訴B已經做完了, 可以來拿結果了
今天要解釋的就是第三種情況。
假設今天有一個類別A
public class A {
private B b;
public A(B b) {
this.b = b;
}
public void handleLongTask(){
try {
System.out.println("A task is running.");
Thread.sleep(1000);
b.handleEvent("ok");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
它執行一個很長時間的任務。
然後有一個類別B, 必須等待A執行完畢, 才可以執行B要執行的任務。
public class B {
public void handleEvent(String result){
int i = 0;
if(result.equals("ok")){
System.out.println("A task is finished.");
}
//B自己的任務
while(i < 100){
i++;
}
System.out.println("B task is finished");
}
}
在main方法內
public static void main(String[] args) {
B b = new B();
A a = new A(b);
a.handleLongTask();
}
會看到輸出結果是
A task is running.
A task is finished.
B task is finished
但是這樣其實很沒有效率的,
如果能夠在A執行的時候, B持續進行它跟A無關的任務, 那該有多好?
其實這是辦得到的,
只需要透過Listener就可以簡單完成這樣的功能,
首先我們先在A建立一個interface。
public interface OnCompletedListener{
void onCompleted(String result);
}
private OnCompletedListener mOnCompletedListener;
public void setOnCompletedListener(OnCompletedListener listener){
mOnCompletedListener = listener;
}
接著在A的長任務內執行
public void handleLongTask(){
try {
System.out.println("A task is running.");
Thread.sleep(1000);
if(mOnCompletedListener != null){
mOnCompletedListener.onCompleted("ok");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
B的類別改成這樣
public class B {
private A a;
public B(A a) {
this.a = a;
a.setOnCompletedListener(new A.OnCompletedListener() {
@Override
public void onCompleted(String result) {
if(result.equals("ok")){
System.out.println("A task is finished.");
}
}
});
}
public void handleEvent(){
int i = 0;
while(i < 100){
i++;
}
System.out.println("B task is finished");
}
}
而我們的main方法改成
public static void main(String[] args) {
public static void main(String[] args) {
A a = new A();
final B b = new B(a);
//A的任務
Executors.newSingleThreadExecutor().submit(new Runnable() {
@Override
public void run() {
a.handleLongTask();
}
});
//B的任務
Executors.newSingleThreadExecutor().submit(new Runnable() {
@Override
public void run() {
b.handleEvent();
}
});
}
}
透過兩條獨立的Thread來分別執行A與B的任務,
可以看出A跟B的任務都獨立開來了,
只要A執行完畢透過Listener來通知B執行結束,
這麼一來B即使在執行自己的任務, 也不會因為等待A而停滯。
結果如下
A task is running.
B task is finished
A task is finished.