高并发编程_Java线程基础 2.线程生命周期
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了高并发编程_Java线程基础 2.线程生命周期,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4633字,纯文字阅读大概需要7分钟。
内容图文
![高并发编程_Java线程基础 2.线程生命周期](/upload/InfoBanner/zyjiaocheng/839/17f59ff6d70f470bb78ec74c8e8c83db.jpg)
高并发编程_Java线程基础 2.线程生命周期
1.线程生命周期图解
当new Thread是,此时线程处于新建状态,并且此时并没有真正启动一个线程。
当调用start方法启动线程时,线程由新建状态变为可运行状态。此时线程仍然没有真正的执行业务逻辑处理。
当线程之间竞争CPU资源,期中一个线程获取到CPU的使用权时,该线程变成运行状态,此时可执行真正的业务逻辑。其他为竞争到CPU使用权的线程仍然处于可运行状态。
当运行中的线程调用wait、sleep、join等方法后,线程进入等待/睡眠/阻塞状态。当线程被notify或者notifyall时,或者sleep时间已到时,线程会重新进入到可运行状态,参与CPU使用权竞争。如果线程执行完毕或者执行过程中异常退出,则线程生命周期结束,线城死亡。
2.线程API重点方法解析
2.1 setDaemon(boolean on),设置线程是否为守护线程,默认为false
public class DaemonThread {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " running");
Thread.sleep(100000);
System.out.println(Thread.currentThread().getName() + " done.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
t.setDaemon(true);
Thread.sleep(5000); //JDK1.7
System.out.println(Thread.currentThread().getName());
}
}
当设置setDaemon方法的参数为true时,当前线程变为守护线程。且setDaemon方法只能放在start方法后面,否则会抛出异常IllegalThreadStateException。当线程为守护线程时,具有一个重要的特点,该特点常用于开发中,如心跳健康监测,线程关闭等。该特点就是如果当前线程结束了,那么当前线程的子线程如果是守护线程,也会结束生命周期。不管守护线程时候还有活动,都会立刻终止。
可通过isDaemon()方法判断该线程是否是守护线程。
2.2 sleep方法
sleep有两个静态的重载方法,参数为睡眠的事件数。两个重载方法的不同点在于两个参数的方法睡眠时间可精确到微妙。
sleep表示让线程短暂睡眠指定时间,在睡眠过程让出CPU使用权给其他线程,但是并没有释放掉对象锁,并且仍然保持着监控状态。放线程睡眠时间已过时,或自动恢复到运行状态。
而对于wait方法来说,首先它不是Thread的方法,而是Object的方法。当调用wait方法时,线程进入阻塞状态。只有通过notify或者notifyall去唤醒该线程,该线程才会从新进入可运行状态,参与COU使用权竞争。
2.3 join方法
当前线程等待调用线程,知道调用线程死亡(Waits for this thread to die.)。
案例解析:
public class ThreadJoin {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10_000);
System.out.println("this Thread is " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "test1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10_000);
System.out.println("this Thread is " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "test2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("main is done");
}
}
//输出结果为
this Thread is test2
this Thread is test1
main is done
t1、t2线程调用join方法后,main线程需要等待t1、t2线程执行完成才能结束。如果t1、t2线程一直在执行,则main线程会一直等待下去,直到死亡。
2.4 Interrupt方法
官方文档解释如下:
如果某个线程调用wait、join、sleep方法进入等待/睡眠/阻塞状态,调用interrupt方法,可打断该线程,并且可捕获到异常InterruptedException。需要注意的是,哪个线程调用
wait、join、sleep方法,该线程调用interrupt方法,才会进行打断。
public class ThreadInterrupt {
private static final Object MONITOR = new Object();
public static void main(String[] args) {
Thread t = new Thread() {
@Override
public void run() {
while (true) {
}
}
};
t.start();
Thread main = Thread.currentThread();
Thread t2 = new Thread() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
main.interrupt();
System.out.println("interrupt");
}
};
t2.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此案例中,调用t.join之后,main线程进入等待状态,等待其他t线程完毕。此时,只有通过main.interrupt()才会打断main线程,捕获到异常。
2.5 notify和notifyall解析
wait、notify和notifyAll方法都是定义在Object类中的方法,且都为final类型的本地方法。放在Object类中的初衷是因为考虑到synchronized的使用。因为这三个方法只能放到synchronized块中使用,否则会抛出IllegalMonitorStateException异常。使用这三个方法时,必须先获取对象的锁。 在一个加了锁的对象上,调用wait方法的目的是使得该线程让出给对象的锁资源,进入等待状态。而加锁的资源对象可能是任何类型的,对于任何类型的加锁对象,调用方法只能放到Object中。notify和notifyall同理。
notify:调用notify方法,随机唤醒等待线程中的一个线程,具体唤醒哪个线程,无法控制。如果只有一个等待状态的线程,则一定会唤醒该线程。
notifyall:唤醒所有等待中的线程。
notify、notifyall方法的具体使用后续章节在进行介绍。
此次线程相关介绍就到这里,如有描述不当地方,请指正。
内容总结
以上是互联网集市为您收集整理的高并发编程_Java线程基础 2.线程生命周期全部内容,希望文章能够帮你解决高并发编程_Java线程基础 2.线程生命周期所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。