Join线程
Thread提供了让一个线程等待另一个线程完成的方法:join()方法
代码演示:
package com.dalingjia.thead;
public class JoinThread extends Thread{
public JoinThread(String name) {
super(name);
}
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println(this.getName()+"\t"+i);
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
if (i==20) {
JoinThread joinThread = new JoinThread("加入的线程");
joinThread.start();
try {
joinThread.join();//main线程必须等joinThread结束才会向下执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
}
}
join()方法主要有2中重载形式:
- join(): 等待被join的线程执行完毕;
- join(long millis): 等待被join的线程的时间最长为millis毫秒。如果在millis毫秒内被join的线程还没有执行结束,则不再等待。
Thread.join其实底层是通过wait/notifyall来实现线程的通信达到线程阻塞的目的;当线程执行结束以后,会触发两个事情,第一个是设置native线程对象为null、第二个是通过notifyall方法,让等待在joinThread对象锁上的wait方法被唤醒。
后台线程
有一种线程,它是在后台运行的,它的任务是为其他线程提供服务,这种线程被称为“后台线程”,JVM的垃圾回收线程就是典型的后台线程。调用Thread对象的setDaemon(true)方法可将指定线程设置成后台线程。
后台线程的特征:如果所有的前台线程都死亡,后台线程会自动死亡。
演示:
package com.dalingjia.thead;
public class DaemonThread extends Thread{
public DaemonThread(String name){
super(name);
}
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println(this.getName()+"\t"+i);
}
}
public static void main(String[] args) {
DaemonThread dt = new DaemonThread("守护线程");
//将该线程设置为后台线程
dt.setDaemon(true);
dt.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"---------\t"+i);
}
//前台线程死亡后,jvm通知后台线程死亡需要一定的时间
}
}
注意:前台线程死亡后,JVM会通知后台线程死亡,但从他接受指令到做出响应,需要一定的时间;而且要将某个线程设置为后台线程,必须在该线程启动之前设置。
线程睡眠sleep和线程让步yield的区别:
- sleep()方法暂停当前线程后会给其他线程执行机会,不会理会其他线程的优先级;但yield()方法只会给优先级相同,或优先级更高的线程执行机会;
- sleep()方法会将线程进入阻塞状态,而yield()进入就绪状态,因此完全有可能某个线程调用yield()方法暂停之后,立即再次获得处理器资源被执行;
- sleep()方法声明抛出InterruptedException异常,所以调用sleep()方法时要么捕捉要么抛出;而yield()方法则不需要。
注意:sleep()和yield()方法来暂停当前线程的执行,但是当前线程不会释放同步监视器。
sleep和wait的区别
它们最大本质的区别是:sleep()不释放同步锁,wait()释放同步锁.
- sleep()方法正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!);wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度);
- wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用;
- sleep()是线程类Thread的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,再次获得对象锁才会进入运行状态。