「java通知机制」java消息通知系统
今天给各位分享java通知机制的知识,其中也会对java消息通知系统进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
java中的事件监听是怎样实现随时监听的,是通过线程吗
java中的事件监听不是通过线程实现的,它是通过一种注册--通知机制实现的。在java的设计模式中,有一种模式叫:观察者模式,和这个类似。
举个例子,本例子是一个简单的监听当数据发生变化时要做的操作:
1,我们先定义一个接口,可以让多个监听者实现
2、实现一监听者
3、被监听者
4、main方法里面是监听的应用。这样就可以监听DataManager中的updateData行为了,当有数据发生变化时,就可以即时被监听者收到。
25 NotificationListenerService通知机制
Android应用除了组件和窗口管理,还有通知显示也是非常重要的,通知是应用界面之外向用户显示的界面。 NotificationListenerService继承于Service,该服务是为了给app提供获取通知的新增和删除事件,通知的数量和内容等相关信息的途径,该类的主要方法:
常见的Flags:
关于前台服务是用户可感知的,前台服务需要显示一个通知,比如后台播放音乐。
创建通知过程,此处的PendingIntent是当通知被点击后的跳转动作,可以是启动Activity、Service,或者发送Broadcast。 对于更新通知只需要发送notifyID相同的通知即可。
除了调用NotificationManager的cancel()或者cancelAll(),也可
点击查看大图
点击查看大图
可见,通知发送与通知取消流程的步骤一直对齐,这里就只介绍通知发送流程,通知取消流程就不再介绍。
[- NotificationManager.java]
在App端调用NotificationManager类的notify()方法,最终通过binder调用,会进入system_server进程的 NotificationManagerService(简称NMS),执行enqueueNotificationWithTag()方法。
[- NotificationManagerService.java]
这个过程主要功能:
接下来看看WorkerHandler到底运行在哪个线程,这需要从NMS服务初始化过程来说起:
[- SystemServer.java]
该过程运行在system_server进程的主线程。
[- SystemServiceManager.java]
该过程先创建NotificationManagerService(简称NMS),然后再调用其onStart方法。
[- NMS.java]
到此,我们可以得知onStart()过程创建的mHandler运行在system_server的主线程。那么上面的执行流便进入了 system_server主线程。
[- NMS.java]
这里的mListeners是指NotificationListeners对象
[- NMS.java]
这里是在system_server进程中第二次采用异步方式来处理。
此处的listener来自于ManagedServiceInfo的service成员变量,listener数据类型是NotificationListenerWrapper的代理对象,详见第三大节。 此处sbnHolder的数据类型为StatusBarNotificationHolder,继承于IStatusBarNotificationHolder.Stub对象,经过binder调用进入到systemui进程的 便是IStatusBarNotificationHolder.Stub.Proxy对象。
[- NotificationListenerService.java]
此时运行在systemui进程,sbnHolder是IStatusBarNotificationHolder的代理端。 此处mHandler = new MyHandler(getMainLooper()),也就是运行在systemui主线程的handler
[- NotificationListenerService.java]
此处调用NotificationListenerService实例对象的onNotificationPosted()
[- BaseStatusBar.java]
此处的mHandler便是systemui的主线程
[- PhoneStatusBar.java]
如果创建的通知视图为空则会直接返回。
[- BaseStatusBar.java]
[- SystemServer.java]
[- SystemServer.java]
启动服务SystemUIService,运行在进程com.android.systemui,接下来进入systemui进程
[- SystemUIService.java]
服务启动后,先执行其onCreate()方法
[- SystemUIApplication.java]
此处以SystemBars为例来展开
[- SystemUIApplication.java]
[- SystemBars.java]
[- SystemBars.java]
config_statusBarComponent的定义位于文件config.xml中,其值为PhoneStatusBar。
[- PhoneStatusBar.java]
[- BaseStatusBar.java]
[- NotificationListenerService.java]
经过binder调用,向system_server中的NMS注册监听器
[- NMS.java]
mListeners的对象类型为ManagedServices。此处的INotificationListener便是NotificationListenerWrapper的代理对象
[- ManagedServices.java]
[- ManagedServices.java]
[- ManagedServices.java]
可见,前面的listener的对端便是运行在systemui中的NotificationListenerWrapper的代理对象。
整个过程涉及到3个Handler都是运行在system_server的主线程:NMS的mHandler,NLS的mHandler以及BaseStatusBar的mHandler。
一次通知发送的过程,在system_server进程里面经过了步骤[2.3],[2.4]的两次异步调用,进入systemui进程,也经历[2.6],[2.8]共两次异步调用。 本身是异步调用,再进过一次异步意义并不大。
另外,这里需要注意的是前台服务也会显示通知,该通知是为了提升服务的优先级,并且让用户可感知该服务的存在,以防止进程被杀,比如音乐播放。 对于常规的通知可通过点击通知(允许清除的通知)或者点击通知栏的清除按钮来清除。
深入理解wait--notify机制
前言
我们知道,java的wait/notify的通知机制可以用来实现线程间通信。wait表示线程的等待,调用该方法会导致线程阻塞,直至另一线程调用notify或notifyAll方法才可另其继续执行。经典的生产者、消费者模式即是使用wait/notify机制得以完成。在这篇文章中,我们将深入解析这一机制,了解其背后的原理。
线程的状态
在了解wait/notify机制前,先熟悉一下java线程的几个生命周期。分别为初始(NEW)、运行(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)、终止(TERMINATED)等状态(位于java.lang.Thread.State枚举类中)。
以下是对这几个状态的简要说明,详细说明见该类注释。
对于以上线程间的状态及转化关系,我们需要知道
WAITING(等待状态)和TIMED_WAITING(超时等待)都会令线程进入等待状态,不同的是TIMED_WAITING会在超时后自行返回,而WAITING则需要等待至条件改变。
进入阻塞状态的唯一前提是在等待获取同步锁。java注释说的很明白,只有两种情况可以使线程进入阻塞状态:一是等待进入synchronized块或方法,另一个是在调用wait()方法后重新进入synchronized块或方法。下文会有详细解释。
Lock类对于锁的实现不会令线程进入阻塞状态,Lock底层调用LockSupport.park()方法,使线程进入的是等待状态。
wait/notify用例
让我们先通过一个示例解析
wait()方法可以使线程进入等待状态,而notify()可以使等待的状态唤醒。这样的同步机制十分适合生产者、消费者模式:消费者消费某个资源,而生产者生产该资源。当该资源缺失时,消费者调用wait()方法进行自我阻塞,等待生产者的生产;生产者生产完毕后调用notify/notifyAll()唤醒消费者进行消费。
public class ThreadTest {
private static final Object obj = new Object();
private static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Thread produce = new Thread(new Produce(), "Produce");
Thread consume = new Thread(new Consume(), "Consume");
consume.start();
Thread.sleep(1000);
produce.start();
}
// 生产者线程
static class Produce implements Runnable {
@Override
public void run() {
synchronized (obj) {
System.out.println("进入生产者线程");
System.out.println("生产");
flag = true;
obj.notify();
System.out.println("退出生产者线程");
}
}
}
// 消费者线程
static class Consume implements Runnable {
@Override
public void run() {
synchronized (obj) {
System.out.println("进入消费者线程");
System.out.println("wait flag 1:" + flag);
while (!flag) {
try {
System.out.println("还没生产,进入等待");
obj.wait();
System.out.println("结束等待");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("wait flag 2:" + flag);
System.out.println("消费");
System.out.println("退出消费者线程");
}
}
}
}
理解了输出结果的顺序,也就明白了wait/notify的基本用法。有以下几点需要知道:
在示例中没有体现但很重要的是,wait/notify方法的调用必须处在该对象的锁(Monitor)中,也即,在调用这些方法时首先需要获得该对象的锁。否则会爬出IllegalMonitorStateException异常。
从输出结果来看,在生产者调用notify()后,消费者并没有立即被唤醒,而是等到生产者退出同步块后才唤醒执行。(这点其实也好理解,synchronized同步方法(块)同一时刻只允许一个线程在里面,生产者不退出,消费者也进不去)
注意,消费者被唤醒后是从wait()方法(被阻塞的地方)后面执行,而不是重新从同步块开头。
深入了解
这一节我们探讨wait/notify与线程状态之间的关系。深入了解线程的生命周期。
由前面线程的状态转化图可知,当调用wait()方法后,线程会进入WAITING(等待状态),后续被notify()后,并没有立即被执行,而是进入等待获取锁的阻塞队列。
对于每个对象来说,都有自己的等待队列和阻塞队列。以前面的生产者、消费者为例,我们拿obj对象作为对象锁,配合图示。内部流程如下
当线程A(消费者)调用wait()方法后,线程A让出锁,自己进入等待状态,同时加入锁对象的等待队列。
线程B(生产者)获取锁后,调用notify方法通知锁对象的等待队列,使得线程A从等待队列进入阻塞队列。
线程A进入阻塞队列后,直至线程B释放锁后,线程A竞争得到锁继续从wait()方法后执行。
关于java通知机制和java消息通知系统的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
发布于:2022-12-11,除非注明,否则均为
原创文章,转载请注明出处。