Java利用监听者实现多线程任务执行状态的监听

监听者 

/**
 * @author 12130
 * @date 2019/11/26
 * @time 22:35
 */
public interface LifeCycleListener {
    // 当出现某些事件的时候,通知监听者
    void onEvent(ObservableRunnable.RunnableEvent event);
}

监听者的实现类

/**
 * @author 12130
 * @date 2019/11/26
 * @time 22:39
 * <p>
 * 监听者的实现类,监听任务的执行情况
 */
public class ThreadLifeCycleObserver implements LifeCycleListener {
    private final Object LOCK = new Object();


    @Override
    public void onEvent(ObservableRunnable.RunnableEvent event) {
        synchronized (LOCK) {
            System.out.println("The runnable (" + event.getThread().getName() + ") date changed and state is" + event.getState());
            if (event.getCause() != null) {
                System.out.println("The runnable (" + event.getThread().getName() + ") process fail");
                event.getCause().printStackTrace();
            }
        }
    }
}

被监听者

package E_观察者模式观察线程的声明周期;

/**
 * @author 12130
 * @date 2019/11/26
 * @time 22:34
 * <p>
 * 任务的包装类,因为我这里只监听任务的开始,结束,异常三种状态,所以直接写一个包装类来包装我们的任务
 * 复用代码的同时也避免了对我们任务类的代码侵入。
 * 但是如果你想监听一个任务具体的执行的中间过程的话,这样就不行了,就必须要在run()方法里面在任务的时刻通知监听者
 * <p>
 * 比如现在你写了一个爬虫程序,有这个爬虫程序执行有三个时期
 * 1、获取url
 * 2、爬取数据
 * 3、数据分析
 * 很明显这种情况下就必须要对在run()方法中在每个状态的结束主动的通知监听者类,也就是说必须要有对任务类的代码侵入。
 * 或者说自定义一个任务类,在任务类中把任务划分,去监听执行的过程
 */
public final class ObservableRunnable implements Runnable {
    /**
     * 监听者
     */
    protected final LifeCycleListener listener;
    /**
     * 包装的任务类
     */
    private final Runnable task;

    public ObservableRunnable(LifeCycleListener listener, Runnable task) {
        this.listener = listener;
        this.task = task;
    }

    @Override
    public void run() {
        try {
            // 通知任务开始执行
            notifyChange(new RunnableEvent(RunnableState.RUNTIME, Thread.currentThread(), null));
            task.run();
            // 任务执行结束
            notifyChange(new RunnableEvent(RunnableState.DONE, Thread.currentThread(), null));
        } catch (Throwable e) {
            // 任务执行错误
            notifyChange(new RunnableEvent(RunnableState.ERROR, Thread.currentThread(), e));
        }
    }

    protected void notifyChange(final RunnableEvent event) {
        listener.onEvent(event);
    }

    public enum RunnableState {
        /**
         * 任务执行中
         */
        RUNTIME,
        /**
         * 任务执行错误
         */
        ERROR,
        /**
         * 任务执行结束
         */
        DONE
    }

    public static class RunnableEvent {
        private final RunnableState state;
        private final Thread thread;
        private final Throwable cause;

        public RunnableEvent(RunnableState state, Thread thread, Throwable cause) {
            this.state = state;
            this.thread = thread;
            this.cause = cause;
        }

        public RunnableState getState() {
            return state;
        }

        public Thread getThread() {
            return thread;
        }

        public Throwable getCause() {
            return cause;
        }
    }
}

测试类

import java.util.Arrays;
import java.util.List;

/**
 * @author 12130
 * @date 2019/11/26
 * @time 22:47
 */
public class ThreadLifeCycleClient {
    public static void main(String[] args) {
        List<String> ids = Arrays.asList("1", "2", "3", "4");
        ThreadLifeCycleObserver observer = new ThreadLifeCycleObserver();
        // 将任务使用我们的包装类进行包装
        ids.forEach(name -> new Thread(new ObservableRunnable(observer, () -> {
            System.out.println("当前任务正在执行一些操作");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }), name).start());
    }
}

 

观察者执行的过程:

实现观察者模式有很多形式,比较直观的一种是使用一种“注册—通知—撤销注册”的形式。

观察者

(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。

被观察

被观察对象发生了某种变化(如图中的SomeChange),从容器中得到所有注册过的观察者,将变化通知观察者。

撤销观察

观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现,这一点为程序提供了更大的灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值