Hike News
Hike News

Java多线程(二)-控制线程

Java线程Thread提供一些工具方便控制线程的执行。

join线程

Thread提供了让一个线程等待另一个线程完成的方法——join()方法,当程序调用线程的join()方法时,调用线程(比如主线程)将被阻塞,直到被join()方法加入的join线程执行完为止。

1
2
3
JoinThread jt = new JoinThread("被join的线程");
jt.start();//main线程调用了子线程jt的join方法
jt.join();//jt线程结束,主线程才会执行

join()方法有三种形式:

  • join():等待join的线程执行完成
  • join(long millis):等待最长millis毫秒时间,若join了的线程还没结束,不再等待。
  • join(long millis,int nanos):等待最长millis毫秒加nanos毫微秒时间。
后台线程

顾名思义,在后台运行的线程,为其他线程提供服务,又称守护线程,例如JVM垃圾回收线程。如果前台的线程全部死亡,后台线程也就没有存在的必要了。

调用线程对象的setDaemon(true)方法可以将指定线程设置为后台线程,Thread类还提供了一个isDaemon()方法,用于判断线程是否为后台线程。主线程默认是前台线程,那子线程默认也是前台线程,后台线程创建的子线程默认是后台线程。需要注意的是,将一个线程设置为后台线程,要在线程启动前设置。

1
2
3
DaemonThread t = new DaemonThread();
t.setDaemon(true);
t.start();
线程睡眠Sleep

再多线程(一)里已经提到过线程的sleep会让线程进入阻塞状态,线程的sleep()方法是Thread类的静态方法,它有两种重载形式:

  • static void sleep(long millis):让当前线程暂停millis毫秒进入阻塞状态,会受系统精度的影响。
  • static void sleep(long millis,long nanos):暂停millis毫秒加nanos毫微秒进入阻塞,同样受精度影响。

无论有没有其他线程,调用sleep方法的线程都不能得到执行。

1
2
3
4
5
6
7
8
public class SleepTest{
public static void main(String[] args) throws Exception{
for(int i=0;i<10;i++){
System.out.println("当前时间:"+ new Date());
Thread.sleep(1000);//暂停1秒
}
}
}
线程让步Yield

sleep()类似的是,线程yield()也是该类的静态方法,但是不同的是它不会阻塞线程,而是让线程进入就绪状态,等待线程调度器的重新调度(有可能下一次被重新调用)。当调用了yield()方法暂停后,只有优先级与当前线程相同或更高的处于就绪状态的线程才会获得执行机会,而sleep()方法不是,暂停之后不会理会其他线程的优先级。

sleep方法声明抛出了InterruptedException异常,所以调用sleep方法时要么捕获该异常,要么显式声明抛出异常;而yield方法没有声明抛出任何异常。

设置线程优先级

线程执行时都具有一定优先级,优先级高的获得较多执行机会。每个线程的优先级与创建它的父线程优先级相同,默认下main线程具有普通优先级,其子线程也具有普通优先级。

Thread类提供了setPriority(int priority)getPriority()方法来设置和获取线程的优先级,其中setPriority()中的参数可以说1~10的整数,也可以是三个静态常量:

  • MAX_PRIORITY:10
  • MIN_PRIORITY:1
  • NORM_PRIORITY:5
1
2
3
4
5
6
public static void main(String[] args){
Thread.currentThread().setPriority(6);
MyThread low = new MyThread();
low.start();
low.setPriority(Thread.MIN_PRORITY);
}

需要说明的事,不同系统的优先级范围并不一样,不一定是1~10,所以应该尽量使用静态常量进行设置。

公众号:菜鸡干Java