虽然Thread为我们提供了可获取状态,以及判断是否alive的方法,但这些方法均是针对线程本身的,而我们提交的任务Runnable在运行过程中所处的状态如何是无法直接获得的,比如它什么时候开始,什么时候结束,最不好的一种体验是无法获得Runnable任务执行后的结果。一般情况下想要获得最终结果,我们不得不为Thread或者Runnable传入共享变量,但是在多线程情况下,共享变量将导致资源的竞争从而增加了数据不一致性的安全隐患。
观察者模式
Observable
接口
package com.example.demo.observer;
public interface Observable {
/**
* current thread running states
*/
enum Cycle
{
STARTED, RUNNING, DONE, ERROR;
}
/**
* get current states of thread
* @return states
*/
Cycle getCycle();
/**
* start the thread
*/
void start();
/**
* interrupt thread
*/
void interrupt();
}
主要暴露给调用者使用,其中四个枚举类型分别代表了当前任务执行生命周期的各个阶段:
getCycle()
方法用于获取当前任务处于哪个执行阶段start()
方法的目的主要是为了屏蔽Thread类其他的API,可通过Observable的
start`对线程进行启动interrupt()
方法的作用和start
一样,可通过Observable
的interrupt
对当前线程进行中断
TaskLifeCycle
接口
package com.example.demo.observer;
public interface TaskLifeCycle<T> {
/**
* if task is start, run this func
*
* @param thread task
*/
void onStart(Thread thread);
/**
* when task is running, run this func
*
* @param thread task
*/
void onRunning(Thread thread);
/**
* when task is finished, run this func
* @param thread task
* @param result result
*/
void onFinish(Thread thread, T result);
/**
* when task run error, run this func
* @param thread task
* @param e {@link Exception}
*/
void onError(Thread thread, Exception e);
/**
* adapter: realize the life cycle implements
* @param <T>
*/
class EmptyLifeCycle<T> implements TaskLifeCycle<T> {
/**
* if task is start, run this func
*
* @param thread task
*/
@Override
public void onStart(Thread thread) {
//do nothing
}
/**
* when task is running, run this func
*
* @param thread task
*/
@Override
public void onRunning(Thread thread) {
}
/**
* when task is finished, run this func
*
* @param thread task
* @param result result
*/
@Override
public void onFinish(Thread thread, T result) {
}
/**
* when task run error, run this func
*
* @param thread task
* @param e {@link Exception}
*/
@Override
public void onError(Thread thread, Exception e) {
}
}
}
定义了在任务执行的生命周期中会被触发的接口,其中EmptyLifeCycle
是一个空的实现,主要是为了让使用者保持对Thread类的使用习惯。
onStart(Thread thread)
当前任务开始执行时会被回调的方法onRunning(Thread thread)
任务运行时会被回调的方法,由于我们针对的是任务的生命周期,不同于线程生命周期中的RUNNING状态,如果当前线程进入了休眠或者阻塞,那么任务都是running状态onFinish(Thread thread, T result)
任务正确执行结束后会被回调,其中result是任务执行后的结果,可允许为nullonError(Thread thread, Exception e)
任务在运行过程中出现任何异常抛出时,onError方法都将被回调,并将异常信息一并传入。
Task
函数接口
package com.example.demo.observer;
@FunctionalInterface
public interface Task<T> {
/**
* task run interface
* 任务执行接口,该接口允许有返回值
* @return T
*/
T call();
}
ObservableThread
实现
是任务监控的关键,继承自Thread类和Observable接口,并且在构造期间需要传入Task的具体实现
package com.example.demo.observer;
public class ObservableThread<T> extends Thread implements Observable {
private final TaskLifeCycle<T> lifeCycle;
private final Task<T> task;
private Cycle cycle;
public ObservableThread(Task<T> task){
this(new TaskLifeCycle.EmptyLifeCycle<>(), task);
}
public ObservableThread(TaskLifeCycle<T> lifeCycle, Task<T> task) {
super();
//Task is not allowed null
if (task == null) {
throw new IllegalArgumentException("The task is required.");
}
this.lifeCycle = lifeCycle;
this.task = task;
}
@Override
public final void run() {
this.update(Cycle.STARTED, null, null);
try {
this.update(Cycle.RUNNING, null, null);
T result = this.task.call();
this.update(Cycle.DONE, result, null);
} catch (Exception e) {
this.update(Cycle.ERROR, null, e);
}
}
private void update(Cycle cycle, T result, Exception e) {
this.cycle = cycle;
if (lifeCycle == null) return;
try {
switch (cycle) {
case STARTED:
this.lifeCycle.onStart(currentThread());
break;
case RUNNING:
this.lifeCycle.onRunning(currentThread());
break;
case DONE:
this.lifeCycle.onFinish(currentThread(), result);
break;
case ERROR:
this.lifeCycle.onError(currentThread(), e);
break;
}
} catch (Exception ex) {
if (cycle == Cycle.ERROR) {
throw ex;
}
}
}
/**
* get current states of thread
*
* @return states
*/
@Override
public Cycle getCycle() {
return this.cycle;
}
}
重写父类的run方法,并且将其修饰为final类型,不允许子类再次对其进行重写,run方法在线程的运行期间,可监控任务在执行过程中的各个生命周期阶段,任务每经过一个阶段相当于发生了一次事件
update方法用于通知时间的监听者,此时任务在执行过程中发生了什么,最主要的通知是异常的处理。如果监听者也就是TaskLifeCycle
,在响应某个事件的过程中出现了意外,则会导致任务的正常执行受到影响,因此需要进行异常捕获,并忽略这些异常信息以保证TaskLifeCycle
的实现不影响任务的正确执行,但是如果任务执行过程中出现错误并且抛出了异常,那么update方法就不能忽略该异常,需要继续抛出异常,保持与call方法同样的意图。
测试类
package com.example.demo.observer;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
Observable observableThread = new ObservableThread<>(() -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" finished done.");
return null;
});
observableThread.start();
}
}
package com.example.demo.observer;
import java.util.concurrent.TimeUnit;
public class Client {
public static void main(String[] args) {
final TaskLifeCycle<String> lifeCycle = new TaskLifeCycle.EmptyLifeCycle<String>() {
public void onFinish(Thread thread, String result) {
System.out.println("The result is " + result);
}
};
Observable observableThread = new ObservableThread<>(lifeCycle, () -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" finished Done.");
return "Hello Observer";
});
observableThread.start();
}
}