线程的优先级
在Java线程中,通过一个整形变量priority
来控制优先级,优先级的范围是[1, 10]
,在线程创建的时候,可以通过Thread#setPriority(int)
方法来修改优先级,默认优先级是5,优先级高的线程分配的CPU时间片的数量要多于优先级低的线程。
示例代码:
public class ThreadPriority { public static void main (String[] args) { Thread thread = Thread.currentThread(); System.out.println(thread.getName() + "(" + thread.getPriority() + ")" ); MyThread t1 = new MyThread ("t1" ); MyThread t2 = new MyThread ("t2" ); t1.setPriority(1 ); t2.setPriority(10 ); t1.start(); t2.start(); } } class MyThread extends Thread { public MyThread (String name) { super (name); } @Override public void run () { Thread thread = Thread.currentThread(); for (int i = 0 ; i < 5 ; i++) { System.out.println(thread.getName() + "(" + thread.getPriority() + ") - " + i); } } }
输出结果不确定。
setPriority()
方法是JVM提供的一个方法,并且能够调用本地方法setPriority0()
。
为什么上述代码的输出结果不确定,我们已经设置了优先级了啊?
现在的计算机都是多核的,线程t1、t2会让哪一个CPU执行结果是不确定的
优先级不代表先后顺序,优先级低的线程也是有可能拿到CPU时间片的,只是CPU时间片的时间比高优先级的线程的时间片时间短
=> 优先级针对的是CPU时间片长短问题。
实际开发中,不必要使用setPriority()
方法。现在都是采用一些信号量控制工具(比如sential、hystrix),实现线程资源的合理调度。其次因为实际运行环境比较复杂,setPriority()
方法难以控制。
结论 :设置线程优先级时,针对频繁阻塞(休眠或者I/O操作)的线程需要设置较高的优先级,而偏重计算的线程需要设置较低的优先级,确保处理器不会被独占。
守护线程
Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个JVM中不存在非守护线程时,JVM将会退出。
示例代码:
public class ThreadDaemon { public static void main (String[] args) { Thread thread = new Thread (new DaemonThread (), "Daemon Thread" ); thread.setDaemon(true ); thread.start(); } static class DaemonThread implements Runnable { @Override public void run () { try { Thread.sleep(5000 ); } catch (InterruptedException e) { System.out.println(e.getMessage()); } finally { System.out.println("FINISH!" ); } } } }
输出结果:不会输出"FINISH!"
finally
块不能保证守护线程的最终执行结果。因此在构建Daemon线程时,不能依靠finally块中的内容来确保执行关闭或者清理资源的逻辑。
来看看setDaemon()
方法:
public final void setDaemon (boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException (); } daemon = on; }
注释上和代码中都可以看出,必须要在线程执行start()
方法之前设置为守护线程,否则会抛出IllegalThreadStateException
异常。
资料:https://www.bilibili.com/video/BV1xM411Z7Ka/ 强推 河北王校长