1. 线程创建的两种方式(继承Thread类、实现Runnable接口)。
(1)继承Thread类
(2)实现Runnable接口
2. Thread类与Runnable接口两种方式比较
(1)Runnable方式可以避免Thread方式由于Java单继承特性带来的缺陷。
(2)Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况。
3. 线程的生命周期和守护线程
3.1 线程的声明周期
(1)创建:新建一个线程对象,如Thread thd = new Thread();
(2)就绪:创建了线程对象后,调用了线程的start()方法(注意:此时线程只是进入了线程队列,等待获取CPU服务,具备了运行的条件,但并不一定已经开始运行了)。
(3)运行:处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run()方法里面的逻辑。
(4)终止:线程的run()方法执行完毕,或者线程调用了stop()方法,线程便进入终止状态。
(5)阻塞:一个正在执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了stop()方法。
3.2 守护线程理论知识
3.2.1 线程分类
(1)用户线程:运行在前台,执行具体的任务。
程序的主线程、连接网络的子线程等都是用户线程。
(2)守护线程:运行在后台,为其他前台线程服务。
特点:一旦所有用户线程都结束执行,守护线程会随JVM一起结束工作。
应用:数据库连接池中的检测线程
JVM虚拟机启动后的检测线程。
最常见的守护线程:垃圾回收线程。
如何设置守护线程:
可以通过调用Thread类的setDaemon(true)方法来设置当前的线程为守护线程。
3.2.2 守护线程注意事项
(1)setDaemon(true)必须在start()方法之前调用,否则会抛出IllegalThreadStateException异常。
(2)在守护线程中产生的新线程也是守护线程。
(3)不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑。
3.2.3 使用jstack生成线程快照
可以使用jstat.exe(命令行工具)或者jviaualvm.exe(界面化工具)生成线程快照。
jstack作用:
生成JVM当前时刻线程的快照(threaddump,即当前线程中所有线程的信息)。
其目的:帮助定位程序问题出现的原因,如长时间停顿、CPU占用率过高等。
可以在java 的jdk安装目录的bin文件夹下使用。
jstack使用可参考网址:https://www.cnblogs.com/wuchanming/p/7766994.html
4. 总结
主要记录的线程创建的两种方式以及该两种方式的比较,建议多使用Runnable这种方式创建线程。
(1)程序中的同一资源指的是同一个Runnable对象。
(2)安全的程序中需要加入同步(Synchronized)。
然后讲解了线程的声明周期、守护线程以及jstack生成线程快照的使用。