java中的事件监听不是通过线程实现的,它是通过一种注册--通知机制实现的。在java的设计模式中,有一种模式叫:观察者模式,和这个类似。
举个例子,本例子是一个简单的监听当数据发生变化时要做的操作:
1,我们先定义一个接口,可以让多个监听者实现
2、实现一监听者
3、被监听者
4、main方法里面是监听的应用。这样就可以监听DataManager中的updateData行为了,当有数据发生变化时,就可以即时被监听者收到。守护线程需要将指定线程的setDaemon()置为true,整体代码为:
import java.util.Random
import java.util.Scanner
public class Main {
public static void main(String[] args) {
System.out.println("main线程启动")
//设置main线程退出监听线程,当maim线程真正结束时,会打印该日志
Runtime.getRuntime().addShutdownHook(new Thread(() ->System.out.println("main开始退出")))
//设置线程1,死循环,每3秒输出一个随机整数
Thread thread1 = new Thread(() ->{
System.out.println("线程1启动")
while (true) {
Random random = new Random()
System.out.println("线程1输出随机整数:[" + random.nextInt(100) + "]")
try {
Thread.sleep(3 * 1000)
} catch (InterruptedException e) {
e.printStackTrace()
}
}
})
thread1.setDaemon(true)//守护线程1
//设置线程2,监听“Q”命令,收到命令后线程2结束
Thread thread2 = new Thread(() ->{
System.out.println("线程2启动")
Scanner in = new Scanner(System.in)
String command = ""
while (!"Q".equals(command)) {
System.out.println("线程2等待输入")
command = in.nextLine()
System.out.println("线程2输入:[" + command + "]")
}
System.out.println("线程2收到终止命令,线程2已结束")
})
thread1.start()
thread2.start()
System.out.println("main线程结束,等待子线程结束")
}
}
关键在于第23行:thread1.setDaemon(true)//守护线程1
我们分析一下我的这段代码,main函数启动后,会先后开始执行线程1和线程2,之后main线程结束,等待所有子线程结束后,main线程即可退出,同时关闭jvm。
我们先看一下如果线程1没有设置为守护线程会咋样,可以看到,线程1是一个死循环,它自己是永远不会主动结束的,线程2则是当输入“Q”命令后,跳出while循环,结束线程2。
运行一下没有守护线程1的情况:
运行后,线程1一直在输出整数,线程2收到“Q”命令后也结束了,但是线程1还是在输出,main线程也无法停止,jvm将一直存在下去。
现在再运行守护线程1的情况:
线程2收到“Q”命令后,线程2结束,此时由于线程1被守护,main线程开始退出,之后,jvm关闭,守护线程1被自动回收。