线程的基础知识(三)

本文介绍了Java线程相关知识。Join线程可让一个线程等待另一个线程完成,通过wait/notifyall实现阻塞。后台线程为其他线程服务,前台线程死亡后会自动死亡。还对比了线程睡眠sleep和线程让步yield、sleep和wait的区别,如是否释放同步锁、线程状态等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中重载形式:

  1. join(): 等待被join的线程执行完毕;
  2. 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的区别:

  1. sleep()方法暂停当前线程后会给其他线程执行机会,不会理会其他线程的优先级;但yield()方法只会给优先级相同,或优先级更高的线程执行机会;
  2. sleep()方法会将线程进入阻塞状态,而yield()进入就绪状态,因此完全有可能某个线程调用yield()方法暂停之后,立即再次获得处理器资源被执行;
  3. sleep()方法声明抛出InterruptedException异常,所以调用sleep()方法时要么捕捉要么抛出;而yield()方法则不需要。

注意:sleep()和yield()方法来暂停当前线程的执行,但是当前线程不会释放同步监视器。

sleep和wait的区别

它们最大本质的区别是:sleep()不释放同步锁,wait()释放同步锁.

  1. sleep()方法正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!);wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度);
  2. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用;
  3. sleep()是线程类Thread的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,再次获得对象锁才会进入运行状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值