控制线程之join、sleep、yeild、线程的优先级
join线程:当某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。
public class Test2 {
public static void main(String[] args) throws InterruptedException {
Join j1=new Join("新线程");
j1.start();
for (int i = 0; i <100; i++) {
if(i==20){
Join j2=new Join("被Join的线程");
j2.start();
j2.join();
}
System.out.println(Thread.currentThread().getName()+" "+i);
}} }
class Join extends Thread{
String name;
public Join(String name){
this.name=name;}
public void run(){
for (int i = 0; i <100; i++) {
System.out.println(getName()+" "+i);} }}
结果如图:
主方法开始时就启动了名为“新线程”的子线程,该子线程将会和main线程并发执行当i=20时,名为“被join的线程”启动,该线程不会和main线程并发执行,main必须等该线程执行结束后才可以向下执行。
join()方法有三种重载形式:
1、等待被join的线程执行完成
2、join(long millis):等待被join的线程的时间最长为millis毫秒。如果在millis内被join的线程还没执行结束则不再等待。
3、join(long millis,int nanos)等待被join的线程的时间最长为millis毫秒加nanos微妙。
后台线程:在后台运行的线程,它的任务是为其他的线程提供服务。如果所有的前台线程都死亡了,后台线程会自动死亡,因为当整个虚拟机中只剩下后台线程时,程序就没有继续运行的必要了,所以虚拟机也就退出了。调用Thread对象的setDaemon(true)方法可将指定线程设置成后台线程。
public class Test2 {
public static void main(String[] args) throws InterruptedException {
Daemon d1=new Daemon();
d1.setDaemon(true);//将此线程设置成后台线程
d1.start();//启动后台线程
for (int i = 0; i <100; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}//程序执行好此处,前台线程 main结束,后台线程也随之结束
} }
class Daemon extends Thread{
public void run(){
for (int i = 0; i <100; i++) {
System.out.println(getName()+" "+i);
}}}
Thread中的isDaemon()方法,用于判断指定线程是否为后台线程。如要将某个线程设置为后台线程,必须在该线程启动之前设置,即setDaemon(true)必须在start()之前。
线程睡眠sleep:让当前正在执行的线程暂停一段时间并进入阻塞状态
线程让步yield:与sleep有点相似,也可以让正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。当调用了yield方法后,只有优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的线程才会获得执行的机会
public class Test2 {
public static void main(String[] args) {
Yield y1=new Yield("高级");
Yield y2=new Yield("低级");
// y1.setPriority(Thread.MAX_PRIORITY);
y1.start();
// y2.setPriority(Thread.MIN_PRIORITY);
y2.start();} }
class Yield extends Thread{
public Yield(){}
public Yield(String name){
super(name);
}
public void run(){
for (int i = 0; i <100; i++) {
System.out.println(getName()+" "+i);
if(i==20){//当i=20时,使用yield方法让当前线程让步
Thread.yield();
} }}}
结果如图:
sleep与yield方法的区别:
1、sleep方法暂停当前线程后,会给其他线程执行机会i,不会理会其他线程的优先级,但yield方法只会给优先级相同或优先级更高的线程执行机会。
2、sleep会将线程转入阻塞状态,直到经过阻塞时间才会转入就绪状态,而yield只是强制当前线程进入就绪状态,因此有可能某个线程调用yield方法暂停后,立即再次获得处理器资源被执行。
3、sleep方法声明抛出了InterruptedException异常,所以调用sleep时要捕获异常,而yield不用。
4、sleep比yield有更好的可移植性。
改变线程的优先级:
每个线程的默认优先级都与创建它的父线程具有相同的优先级。main函数的默认优先级为普通优先级。
Thread提供了setPriority()和getPriority()方法来设置和返回指定线程的优先级,其中setPriority方法的参数可以是一个整数(1~10),也可以是Thread类的三个静态常量:MAX_PRIORITY(值为10)、MIN_PRIORITY(值为1)、NORM_PRIORITY(值为5)。