Java多线程设计模式——监控任务的生命周期

场景描述

Thread提供了可获取状态、以及判断状态是否alive的方法。然而,这些方法均是针对线程本身的,我们提交的任务在运行过程中所处的状态是无法直接获取的,例如什么时候开始,什么时候结束。

解决方案

观察者模式

当某个对象发生状态改变需要通知第三方时,观察者模式适合这样的工作。应用观察者模式时,使用Thread作为事件源(引发状态发生变化的源头)。Thread作为任务的逻辑单元掌握整个过程的始末。事件的接受者则是接收通知的一方。

接口定义

Observable接口

该接口主要是暴露给调用者使用,其中四个枚举类型分别代表了当前任务执行生命周期的各个阶段。

public interface Observable {

    enum Cycle{
        STARTED,RUNNING,DONE,ERROR
    }

    /**
     * 获取当前线程的生命周期状态
     */
    Cycle getCycle();

    /**
     * 定义启动线程的方法,主要是为了平布Thread的其他方法
     */
    void start();

    /**
     * 定义线程中断的方法,作用域start一样,也是为了屏蔽Thread的其他方法
     */
    void interrupt();
}

TaskLifeCycle接口

TaskLifeCycle接口定义了在任务执行的生命周期中会被处罚的接口,其中EmptyLifeCycle是一个空的实现,主要是为了让市容这保持对Thread类的使用习惯。

public interface TaskLifeCycle<T> {
    /**
     * 任务启动时会触发onStart方法
     * @param thread
     */
    void onStart(Thread thread);

    /**
     * 任务正在运行时会触发onRunning方法
     * @param thread
     */
    void onRunning(Thread thread);

    /**
     * 任务运行结束时触发onFinish方法,其中result是任务执行结束后的结果
     * @param thread
     * @param result
     */
    void onFinish(Thread thread,T result);

    /**
     * 任务执行报错时会触发onError方法
     * @param thread
     * @param e
     */
    void onError(Thread thread,Exception e);

    /**
     * 生命周期接口的空实现(Adapter)
     * @param <T>
     */
    class EmptyLifecycle<T> implements TaskLifeCycle<T>{

        @Override
        public void onStart(Thread thread) {

        }

        @Override
        public void onRunning(Thread thread) {

        }

        @Override
        public void onFinish(Thread thread, T result) {

        }

        @Override
        public void onError(Thread thread, Exception e) {

        }
    }
}

Task接口

监控任务的生命周期是要对线程中的任务执行增加可观察能力,并且需要获得最后的计算结果(即需要监控的对象就是Task的实例)。因此Runnable接口在可观察的线程中将不再被使用,以Task接口取代,它的作用于Runnable类似,主要用于承载任务的执行逻辑单元

public interface Task<T> {
    /**
     * 任务执行的接口,改接口允许有返回值。类似于Runnable中的 run()
     * @return
     */
    T call();
}

ObservableThread实现

ObservableThread是任务监控的关键,它继承Thread类和Observable接口,在构造期间传入Task的具体实现。

public class ObservableThread<T> extends Thread implements Observable {

    /**
     * 事件的监听者。原始的观察者模式这里应该是Observer的集合。
     */
    private final TaskLifeCycle<T> lifeCycle;
    private final Task<T> task;
    private Cycle cycle;

    /**
     * 指定Task的实现,默认情况下使用EmptyLifeCycle
     *
     * @param task
     */
    public ObservableThread(Task<T> task) {
        this(new TaskLifeCycle.EmptyLifecycle<>(), task);
    }

    public ObservableThread(TaskLifeCycle<T> lifeCycle, Task<T> task) {
        super();
        if (task == null) {
            throw new IllegalArgumentException("The task is required.");
        }
        this.lifeCycle = lifeCycle;
        this.task = task;
    }

    /**
     * 重写父类的run方法,并将其修饰为final类型,不允许子类再次对其进行重写。
     * run方法在线程的运行期间,可监控任务在执行过程中的各个生命周期阶段,任务每经过一个
     * 阶段就相当于发生一次事件。
     */
    @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){
            /**
             * 捕获Task运行时所产生的异常,将错误向监听者发送。
             */
            this.update(Cycle.ERROR, null, e);
        }
    }

    @Override
    public Cycle getCycle() {
        return this.cycle;
    }

    /**
     * update方法用于通知事件的监听者,此任务在执行过程中发生了什么,最主要的
     * 是通知异常的处理。
     * @param cycle
     * @param result
     * @param 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){
            /**
             * 监听者也就是TaskLifeCycle,在响应某个事件的过程中出现了意外,
             * 则会导致任务的正常执行受到影响,因此需要进行捕获,并忽略这些异常
             * 信息以保证TaskLifeCycle的实现不影响Task的正确执行,但是如果
             * 是Task在执行过程中出现了异常,则需要把这个异常抛出,保持与call方法
             * 同样的意图。
             */
            if (cycle == Cycle.ERROR){
                throw ex; //Task执行时出现的异常
            }else{
                // 监听者出现的异常,丢弃
            }
        }
    }
}

运行测试

ObservableThread的实现已经完成,首先关注ObservableThread是否保持了与Thread的使用习惯,其次再去关注是否可以实现TaskLifeCycle去监听感兴趣的时间,比如获取最终的计算结果。

public static void main(String[] args) {

    /**
     * ObservableThread -> Thread
     * Task -> Runnable
     * call -> run
     */
    Observable observableThread = new ObservableThread<>(new Task() {
        @Override
        public Object call() {
            try{
                System.out.println("running");
                TimeUnit.SECONDS.sleep(2);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("finished done.");
            return null;
        }
    });
    observableThread.start();

下面这个例子定义了一个需要返回值的ObservableThread,重写了TaskLifeCycle中的方法。

    public static void main(String[] args) {
        TaskLifeCycle<String> lifeCycle = new TaskLifeCycle<String>() {
            @Override
            public void onStart(Thread thread) {
                System.out.println("start Task");
            }

            @Override
            public void onRunning(Thread thread) {
                System.out.println("Task is running");
                int i = 1/0; // 监听者产生异常
            }

            @Override
            public void onFinish(Thread thread, String result) {
                System.out.println("finish");
                System.out.println("result is "+result);
            }

            @Override
            public void onError(Thread thread, Exception e) {
                e.printStackTrace();
            }
        };



        Observable observableThread = new ObservableThread<String>(lifeCycle, new Task<String>() {
            @Override
            public String call() {
                try{
                    TimeUnit.SECONDS.sleep(2);
//                    int i = 1/0; // Task产生异常
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                return "Hello Observer";
            }
        });
        observableThread.start();
    }

或者只实现部分方法。

TaskLifeCycle<String> lifeCycle = new TaskLifeCycle.EmptyLifecycle<String>() {
    @Override
    public void onFinish(Thread thread, String result) {
        System.out.println("finish");
        System.out.println("result is "+result);
    }
};

ThreadPoolExecutor.runWorker()

在JUC中,ThreadPoolExecutor代表了一个线程池,其中runWorker() 方法是执行任务的方法。其中调用了beforeExecute() 、afterExecute() 和terminated() 方法来扩展任务的执行。

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);
                }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

总结

  1. 接口Observable中定义了与Thread同样的方法用于屏蔽Thread中的其他API。这就是为什么在使用过程中用Observable声明ObservableThread对象。
  2. 将ObservableThread中的run方法修饰为final,或者将ObservableThread类修饰为final,防止子类继承重写,导致整个生命周期的监控失效。
  3. ObservableThread中的run方法充当了事件源的发起者TaskLifeCycle监听者,是事件回调的响应者。

Reference

《Java高并发编程详解》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值