1、Daemon线程
Daemon线程称为守护线程(非常喜欢这个名字)。线程一旦被设置为守护线程,当非守护线程结束,守护线程即使没有执行完,也必须随之全部结束。例如我们曾经玩儿过的坦克大战,一旦守护的老巢完蛋了,其它守护坦克没死也要结束。
Daemon线程的实质作用是为主线程其他线程的运行提供服务。User Thread线程和Daemon Thread守护线程本质上来说去没啥区别的,唯一的区别之处就在虚拟机的离开:如果User Thread全部撤离,那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。
设定守护线程方法:public final void setDaemon(boolean on) ;但是有几点需要注意:
thread.setDaemon(true)必须在thread.start()之前设置,否则会抛出IllegalThreadStateException异常。因为我们不能够将正在运行的常规线程设为守护线程。
在Daemon线程中产生的新线程也是Daemon的。
不是所有的应用都可以分配给Daemon线程来进行服务,比如读写操作或者计算逻辑。我们必须防止在Daemon Thread还没来的及进行操作时,虚拟机可能已经退出了。
2、Daemon实例
(1)待设置为Daemon线程的线程类
<span style="font-size:18px;">//实现Runnable接口
public class DaemonDemo implements Runnable {
//重写run方法
@Override
public void run() {
for (int x = 0; x < 1000; x++) {
System.out.println(Thread.currentThread().getName() + "---" + x);
}
}
}</span>
(2)测试类
<span style="font-size:18px;">public class DaemonDemoTest {
public static void main(String[] args) {
DaemonDemo dd = new DaemonDemo();
Thread t1 = new Thread(dd);
Thread t2 = new Thread(dd);
//将t1、t2设置为守护线程,注意要在start()方法调用之前设置
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
for (int x = 0; x < 10; x++) {
System.out.println(Thread.currentThread().getName() + "---" + x);
}
}
}</span>
运行结果:main线程中的10次循环结束时,两个没有执行结束的守护线程都会随之结束。
3、Join线程
当线程被调用了Join()方法,那么其它线程必须等待,直到本线程结束,其它线程才能执行。Join在英文中解释为合并、加入,我更喜欢称之为阻塞线程,程序必须首先执行完阻塞线程才能够去执行其他线程。
Join线程的作用:在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束(正如我们上面的例子),但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
4、Join线程实例
(1)待设置线程类
<span style="font-size:18px;">public class JoinDemo implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + "---" + x);
}
}
}</span>
(2)测试类
<span style="font-size:18px;">public class JoinDemoTest {
public static void main(String[] args) {
PriorityDemo pd = new PriorityDemo();
Thread t1 = new Thread(pd);
Thread t2 = new Thread(pd);
Thread t3 = new Thread(pd);
t1.setName("线程一");
t2.setName("线程二");
t3.setName("线程三");
t2.start();
// join()线程 加入线程
try {
t2.join(); //必须首先将t2执行完毕才能去执行其它线程
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.start();
t3.start();
}
}</span>
运行结果:首先结束t2线程之后才会执行t1和t3线程。