创建线程的两种方式Thread与Runnable
一、简要说明
创建线程的两种方式,一是继承Thread类,二是实现Runnable接口,最后都是依据Thread类的构造方法实例化出一个线程对象,调用线程对象的start()方法,就可以通知线程启动了,在线程获取CPU的资源后,此时线程真正地按照run()方法内部的步骤运行起来了,执行完毕之后,线程消亡。
二、两种方式的比较
(1)继承Thread类。由于java单继承的特性,此类不可再继承其他类,而实现Runnable接口则可以避免这种缺陷。
(2)实现Runnable接口。Runnable内部的代码可以被多个线程(Thread实例)共享,适用于多个线程处理同一资源的情况。
三、代码演示
两种方式都比较简单,没什么好说的。
package day0830;
class MyThread extends Thread {
@Override
public void run() {
System.out.println("继承Thread类");
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("实现Runnable接口");
}
}
public class Test {
public static void main(String args[]) {
//启动继承Thread类创建的线程对象
MyThread t1 = new MyThread();
t1.start();
//启动实现Rinnable接口创建的线程对象
Thread t2 = new Thread(new MyRunnable());
t2.start();
}
}
输出为:
四、线程的生命周期
线程有如下的生命周期
(1)创建:我们实例化线程对象的时候
(2)就绪:创建了线程对象后,调用了线程的start()方法(注意:此时线程只是进入了线程队列,等待获取CPU资源,具备了运行条件,但并不一定已经开始运行了)
(3)运行:处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run()方法里面的逻辑
(4)终止:线程的run()方法执行完毕,或者线程调用了stop()方法(此方法目前已经被废弃,不再建议使用),线程便进入到终止状态
(5)阻塞:一个正在执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入到阻塞状态,如调用了sleep()方法。而一旦线程苏醒后,便再次进入到就绪状态。
线程状态转换图如下:
五、守护线程
java线程有两类:
(1)用户线程,运行在前台,执行具体的任务。程序的主线程、连接网络的子线程等都是用户线程。
(2)守护线程,运行在后台,为前台线程服务。
特点:一旦所有的用户线程都结束运行,守护线程会随着JVM一起结束工作。垃圾回收线程就是一个常见的守护线程。
应用:【1】数据库连接池的监测线程,监测连接个数,连接超时的时间等
【2】JVM虚拟机启动后的监测线程,监测内存使用情况,锁持有的情况等
如何设置守护线程?
可以通过调用Thread类的setDaemon(true)方法来设置当前的线程为守护线程。
注意:【1】setDaemon(true)必须在start()方法之前调用,否则会抛出IllegalThreadStateException异常
【2】在守护线程中产生的新线程也都是守护线程
【3】不是所有的任务的适合分配给守护线程来做,比如读写操作或计算操作