2.7 线程的优先级

2016-05-31 23:19:48 4,187 0


Java中Thread对象有一个优先级的概念,优先级被划分10个级别,创建线程的时候,如果没有指定优先级,默认是5。主线程的优先级也是5。优先级高的线程会比优先级低的线程获得更多的运行机会。

Thread类定义了3个整形常量MAX_PRIORITYNORM_PRIORITYMIN_PRIORITY分别用于表示支持的最高优先级,正常优先级和最低优先级。同时提供了一个getPriority()方法来获取当前线程优先级。

以下代码用户展示上述所提到的内容:

public class PriorityDemo {
    public static void main(String[] args) {
        System.out.println("最大优先级;"+Thread.MAX_PRIORITY);
        System.out.println("正常优先级;"+Thread.NORM_PRIORITY);
        System.out.println("最小优先级;"+Thread.MIN_PRIORITY);
        System.out.println("主线程优先级;"+Thread.currentThread().getPriority());
        Thread t=new Thread();
        System.out.println("创建一个线程默认的优先级:"+t.getPriority());
    }
}

程序的运行结果如下:

最大优先级;10

正常优先级;5

最小优先级;1

主线程优先级;5

创建一个线程默认的优先级:5

以下的案例用于演示优先级高的线程可能比一个优先级低线程获取到更多的运行机会:

public class PriorityDemo2 {
    public static void main(String[] args) {
        //创建线程t2并将优先级设为10
        Thread t1=new Thread("P10"){
            @Override
            public void run() {
                for (int i = 0; i <10 ; i++) {
                    System.out.println(Thread.currentThread().getName()+":执行"+i+"次");
                }
            }
        };
        t1.setPriority(Thread.MAX_PRIORITY);
        //创建线程t2并将优先级设为1
        Thread t2=new Thread("P1"){
            @Override
            public void run() {
                for (int i = 0; i <10 ; i++) {
                    System.out.println(Thread.currentThread().getName()+":执行"+i+"次");
                }
            }
        };
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
    }
}

案例的输出结果如下:

P10:执行0次

P10:执行1次

P10:执行2次

P1:执行0次

P1:执行1次

P1:执行2次

P1:执行3次

P1:执行4次

P1:执行5次

P1:执行6次

P1:执行7次

P1:执行8次

P10:执行3次

P10:执行4次

P10:执行5次

P10:执行6次

P10:执行7次

P10:执行8次

P10:执行9次

P1:执行9次

从结果中我们好像看到优先级高的线程P10好像并没有比优先级低的线程P1在执行的时候有什么优势。这是因为线程的执行是抢占式的,优先级高的线程只是理论上会更优先的获取执行的机会,但并不意味着一定优先执行。

事情真的是这样简单吗?

事实上,并不是所有的操作系统都支持优先级的设置,有些操作系统会直接忽略优先级的设置。因此在实际开发中,尽量不要去设置一个线程运行时的优先级,因为结果可能不是你想要的那样。

提示:可以通过jps+jstack工具查看线程运行时的优先级。

首先通过jps命令查看当前操作系统中正在运行的java进程。

[root@work]# jps -l
21204 PriorityDemo2

21204是进程的编号,你的可能与我不一样,接着使用jstack 21204查看对应进程的线程信息,输出的内容可能会有很多,最好将其导入到一个文件中,我们需要通过搜索关键字"P1"和"P10"找到我们关心的部分。

需要注意的是,不同的操作系统,不同的JVM版本上导出的内容可能是不一样的。以下是笔者在windows和linux系统上的查看结果,JDK版本都是1.8:

windows(win7专业版)

"P1" #10 prio=1 os_prio=-2 tid=0x14f6b000 nid=0x21cc waiting on condition [0x1590f000]

   java.lang.Thread.State: TIMED_WAITING (sleeping)

        at java.lang.Thread.sleep(Native Method)

        at concurrency.chapter2.PriorityDemo2$2.run(PriorityDemo2.java:25)


"P10" #9 prio=10 os_prio=2 tid=0x14f6ac00 nid=0x1928 waiting on condition [0x152df000]

   java.lang.Thread.State: TIMED_WAITING (sleeping)

        at java.lang.Thread.sleep(Native Method)

        at concurrency.chapter2.PriorityDemo2$1.run(PriorityDemo2.java:13)

Linux(Centos 6.5)

"P1" #9 prio=1 os_prio=0 tid=0x00007f24d80cd800 nid=0x52df waiting on condition [0x00007f24c8dfc000]

   java.lang.Thread.State: TIMED_WAITING (sleeping)

        at java.lang.Thread.sleep(Native Method)

        at PriorityDemo2$2.run(PriorityDemo2.java:21)


"P10" #8 prio=10 os_prio=0 tid=0x00007f24d80cc000 nid=0x52de waiting on condition [0x00007f24c8efd000]

   java.lang.Thread.State: TIMED_WAITING (sleeping)

        at java.lang.Thread.sleep(Native Method)

        at PriorityDemo2$1.run(PriorityDemo2.java:9)

其中prio,表示的是JVM设置的优先级,os_prio表示的是对应的操作系统线程的优先级(前面我们提到过,JVM线程和操作系统线程是一一对应的)。

可以看到在windows操作系统上,线程优先级好像是有作用的,P1和P10线程对应的操作系统优先级是不一样的。但是对于CentOS 6.5,可以看到对应的线程优先级都是0,事实上说明,线程的优先级设置被忽略了。