线程的优先级
在操作系统中,线程存在优先级关系,具有高优先级的线程会获得更多CPU的资源,优先级低的线程会获得少的CPU资源呢。在Java虚拟机中,线程的优先级也是如此。在Java中,线程分为10个优先级。下面我们先了解一下线程优先级的性质。
- 线程的优先级具有继承性:即一个类被继承之后优先级也会被继承。
- 线程的优先级具有规则性:高优先级的线程总是大部分情况下先执行完
- 线程优先级具有不确定性:虽然CPU的资源分配的多了,但是线程在执行的时候并不是按照一定计划执行的,所以执行结果往往是不确定的。
如何设置线程的优先级?
Java中使用public final void setPriority(int newPriority)来设置线程的优先级。
下面是一段实例:
public class Main {
public static void main(String[] args){
TestThread test=new TestThread();
test.setPriority(10);
}
public static class TestThread extends Thread{
public void run(){
System.out.println("Hello world");
}
}
}
这段代码把test实例的线程设置为10
写两个线程,设置优先级,观察运行结果。下面是例子:
public class Main {
public static void main(String[] args){
TestThread test=new TestThread();
TestThread test2=new TestThread();
test.setPriority(10);
test2.setPriority(6);
test.start();
test2.start();
}
public static class TestThread extends Thread{
public void run(){
for(int i=0;i<50;i++){
System.out.println(Thread.currentThread().getId()+":"+i);
}
}
}
}
优先级:源码分析
我们现在来看看JDK在线程上的源代码
首先是设置优先级的方法:
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
这也是一个final方法,不能被覆盖,我们发现,JDK中设置优先级要有一个最大值和最小值的,我们来看看这两个值:
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
从这里我们可以看出来线程的优先级分为1-10,中间还有一个值为5.那么5是什么呢?就是线程优先级的默认值,在我们程序中,如果没有规定线程的优先级,那么线程优先级为5。
守护线程
什么是守护线程呢?用过Linux操作系统的童鞋对于Linux下的守护进程一定有了解,守护线程和守护进程的道理基本一致。在Java中,存在两种线程,一种是用户线程,一种是守护线程。守护线程是一种特殊的线程,他在执行的是一种后台服务,当一个系统中不存在非守护线程的时候,守护线程也会自己销毁,典型的守护线程就是JVM的垃圾回收线程。
设置守护线程很简单,下面是一个简单的例子:
public class Main {
public static void main(String[] args) throws InterruptedException {
TheThread theThread=new TheThread();
theThread.setDaemon(true);//设置守护线程
theThread.start();
Thread.sleep(5000);
System.out.println("全都退出啦");
}
public static class TheThread extends Thread{
public void run(){
int i = 0;
while (true){
i++;
System.out.println(Thread.currentThread().getId()+":"+i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
example: 垃圾回收线程就是一个经典的守护线程,当我们的程序中不再有任何运行的Thread,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是JVM上仅剩的线程时,垃圾回收线程会自动离开。它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。
生命周期:守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。也就是说守护线程不依赖于终端,但是依赖于系统,与系统“同生共死”。那Java的守护线程是什么样子的呢。当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则JVM不会退出。
当java虚拟机中没有非守护线程在运行的时候,java虚拟机会关闭。当所有常规线程运行完毕以后,守护线程不管运行到哪里,虚拟机都会退出运行。所以你的守护线程最好不要写一些会影响程序的业务逻辑。否则无法预料程序到底 会出现什么问题。