<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190609155854030-1712068336.png" width="500" /> 线程终止的的缘由: * run()或call()方法执行完成,线程正常结束 * 线程抛出一个未捕获的Exception或Error * 直接调用该线程的stop()方法来结束该线程——该方法容易致使死锁,一般不推荐使用java
class MyThread extends Thread{ public void run(){ System.out.println("子线程"); } } public class StartDead { public static void main(String[] args) throws InterruptedException{ Thread t = new MyThread(); t.start(); while(t.isAlive()){ Thread.sleep(200); } System.out.println(t.isAlive()); t.start(); } }
<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190609163317891-1856666325.png" width="500" />ide
Thread提供了让一个线程等待另外一个线程完成的方法——join()方法。this
class MyThread extends Thread{ String name; public MyThread(String name){ this.name = name; } @Override public void run(){ System.out.println("Hello, "+name+"!"); try{ Thread.sleep(2000); }catch (InterruptedException ex){ ex.printStackTrace(); }finally { System.out.println("Bye,"+name+"!"); } } } public class StartDead { public static void main(String[] args) throws InterruptedException{ Thread t1 = new MyThread("Bob"); System.out.println("start"); t1.start(); t1.join(1000,10); System.out.println("end"); } }
<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190609165330513-1373973209.png" width="500" />spa
<font color=#FF0000>Java的程序入口就是JVM启动main线程,main线程又能够启动其余线程。当全部的线程都运行结束时,JVM退出。 有一种线程是无限循环,如定时任务。若是这种线程不结束,JVM就不能退出。 问题:由谁来结束这些线程?</font> 有一种线程,他是在后台运行的,它的任务是为其余的线程提供服务,这种线程被成为“后台线程(Daemon Thread)”,又称为“守护线程”或“精灵线程”。JVM的垃圾回收线程就是典型的后台线程。 总之:线程
特征:code
建立守护线程:调用Thread的对象的setDaemon(true)方法能够将指定线程设置为后台线程。orm
public class DaemonThread extends Thread{ public void run(){ while(true){ System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))); try{ Thread.sleep(1000); }catch (InterruptedException e){ break; } } } public static void main(String[] args) throws InterruptedException{ System.out.println("Main start"); DaemonThread t = new DaemonThread(); t.setDaemon(true); t.start(); Thread.sleep(5000); System.out.println("Main end"); } }
<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190609205707100-1404414409.png" width="500" />对象
package com.csj2018.lxf; import org.junit.Ignore; import org.junit.Test; class DaemonThread extends Thread{ public void run() { for(int i=0;i<1000;i++) { System.out.println(Thread.currentThread().getName()+"\t"+i); try { Thread.sleep(1000); }catch (InterruptedException e) { e.printStackTrace(); } } } } public class ThreadTest2{ @Test public void test() { Thread t = new DaemonThread(); t.setDaemon(true);//setDaemon(true)必须在start()方法以前调用,不然会引起IllegalThreadStatsException t.start(); for(int i=0;i<3;i++) { System.out.println(Thread.currentThread().getName()+"\t"+i); try { Thread.sleep(1000); }catch (InterruptedException e) { e.printStackTrace(); } } } }
<img src="https://img2018.cnblogs.com/blog/1418970/202002/1418970-20200202004852612-114306420.png" width="500" />blog
若是须要让正在执行的线程暂停一段时间,并进入阻塞状态,能够调用Thread类的静态方法sleep实现。当前线程调用sleep进入阻塞状态后,在其睡眠时间内,该线程不会得到执行的机会,即便系统中没有其余可执行的线程,处于sleep中的线程,依然不会执行。所以sleep经常使用于程序的执行。资源
import java.util.Date; public class SleepTest extends Thread { public static void main(String[] args) throws InterruptedException{ for(int i=0;i<10;i++){ System.out.println("当前时间:"+new Date()); Thread.sleep(1000); } } }
<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190609173630860-1274522324.png" width="500" /> ### 2.4线程让步: yield yield让当前正在执行的线程暂停,但不会阻塞该线程,它只是将该线程转入就绪状态。yield()只是让当前线程暂停一下,让系统的线程调度器从新调度一次,彻底可能的状况:某个线程调用yield方法暂停后,线程调度器又将其调度出来从新执行。 当某个线程用了yield方法暂停以后,只有优先级与当前线程相同,或者优先级比当前线程更高处于就绪状态的线程才会得到执行的机会。 ```#java public class YieldTest extends Thread{ public YieldTest(String name){ super(name); } public void run(){ for(int i=0;i<10;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i==5){ Thread.yield(); } } } public static void main(String[] args) throws InterruptedException{ YieldTest yt1 = new YieldTest("高级"); yt1.setPriority(Thread.MAX_PRIORITY); yt1.start();
YieldTest yt2 = new YieldTest("低级"); yt2.setPriority(MIN_PRIORITY); yt2.start(); }
}
<img src="https://img2018.cnblogs.com/blog/1418970/201906/1418970-20190609175309658-2035292882.png" width="370" /> sleep和yield的区别: * sleep暂停当前线程后,会给其余线程执行机会,不会理会其余线程的优先级;但yield只会给优先级相同或更高的线程执行机会 * sleep将线程转入阻塞状态;yield将线程转入就绪状态 * sleep抛出InterruptedException异常;yield不会 * sleep比yield有更好的移植性 ## 3总结: * Java线程对象Thread的状态包括:New/Runnable/Blocked/Waiting/Timed Waiting/Terminated * 经过对另外一个线程对象调用join()方法能够等待其执行结束 * 能够指定等待时间,超过等待时间线程仍然没有结束就再也不等待 * 对已经运行结束的线程调用join()方法会马上返回 * 守护线程是为其余线程服务的线程 * 全部非守护线程都执行完毕后,虚拟机退出 * 守护线程不能持有资源(如打开文件等)