1.setDeamon:API文档说用了这个方法后就将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。可以这么理解,就把守护线程当成是后台线程,当前台线程在运行的时候,后台线程和其他线程一样,也可以抢cpu资源,没什么区别,但是当前台线程结束之后,后台线程不管什么情况,都会结束。 注意:setDeamon需要在线程启动前执行
Demo1:守护线程
class StopThread implements Runnable{
public void run(){
while(true){
System.out.println(Thread.currentThread().getName()+"....run");
}
}
}
class StopThreadDemo{
public static void main(String[] args) {
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
int num = 0;
while(true){
if(num++ == 60){
break;
}
System.out.println(Thread.currentThread().getName()+"......."+num);
}
System.out.println("over");
}
}
如果将setDaemon那两行注释掉,这个程序会一直运行,但是开启守护线程后,主线程执行完毕,t1,t2两个线程也随之结束。
注意:如果后台线程中有finally,当前台线程结束之后,finally也不会执行,而是直接结束。
2.join:当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
Demo2:join
class Demoj implements Runnable{
public void run(){
for(int x=0; x<30; x++){
System.out.println(Thread.currentThread().toString()+"....."+x);
}
}
}
class JoinDemo{
public static void main(String[] args) throws Exception{
Demoj d = new Demoj();
Thread t1 = new Thread(d);
// Thread t2 = new Thread(d);
t1.start();
// t2.start();
t1.join();
for(int x=0; x<30; x++){
System.out.println("main....."+x);
}
System.out.println("over");
}
}
主线程开启t1,然后执行到t1.join,主线程会一直等待t1的执行,直到t1结束之后,主线程才会继续执行。如果把t2的注释去掉,t1和t2会交替执行,但是主线程会不会执行只跟t1是否执行完有关系。
3.yield:暂停当前正在执行的线程对象,并执行其他线程,但是这个并不总是有效,有可能调用yield的线程依然能够再次抢到cup的执行权。所以yield只能某种程度上让线程交替执行,并不是绝对的。Java编程思想这样写到:yield()的调用是对线程调度器(Java线程机制的一部分,可以将CPU从一个线程转移给另一个线程)的一种建议,它在声明:”我已经执行完生命周期中最重要的部分了,此刻正是切换给其他任务执行一段时间的大好时机。”所以仅仅只是一种建议。
Demo3:yield
class Demo implements Runnable{
public void run(){
for(int x=0; x<30; x++){
System.out.println(Thread.currentThread().toString()+"....."+x);
Thread.yield();
}
}
}
class JoinDemo{
public static void main(String[] args) throws Exception{
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
}
}