Java 多线程(二)之 Thread 优先级

Thread 中线程优先级相关属性

每个线程均有优先级,在 Thread 中, 与优先级对应的属性如下:

/**
 * 线程的优先级属性
 */
private int priority;
/**
 * 线程所能拥有的最大优先级.
 */
public final static int MIN_PRIORITY = 1;

/**
 * 线程默认的优先级.
 */
public final static int NORM_PRIORITY = 5;

/**
 * 线程所能拥有的最大优先级.
 */
public final static int MAX_PRIORITY = 10;

相关函数

在此只讨论 Thread 类中的。

优先级初始化

 private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
    // ....
    this.priority = parent.getPriority();
    setPriority(priority);
   // ....
}

init() 函数对优先级进行了初始化。并调用 setPriority(priority) 函数进行设置。从中得知, 线程的优先级是继承于创建它的线程的。

设置优先级

在 init() 中, 除了给 this.priority 赋值, 还调用了 setPriority(priority) 函数, 因为在该函数内部还调用了一个 native 方法。

public final void setPriority(int newPriority) {
    ThreadGroup g;
    checkAccess();
    // 不能大于最大优先级 MAX_PRIORITY
    if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
        throw new IllegalArgumentException();
    }
    if((g = getThreadGroup()) != null) {
        // 如比所属线程组的最大优先级还大, 则取线程组的最大优先级
        if (newPriority > g.getMaxPriority()) {
            newPriority = g.getMaxPriority();
        }
        setPriority0(priority = newPriority);
    }
}

由代码可知, 设置的优先级不能大于最大优先级,也不能大于所在线程组的最高优先级

获取优先级

获取当前的优先级, 其实就是返回 priority 属性的值。

public final int getPriority() {
    return priority;
}

从以上可知, 在 Thread 中, 线程的优先级有如下特点:

  1. Java 线程的优先级从 1~10;
  2. Java 线程默认优先级是 5;
  3. Java 线程的优先级继承于创建它的线程。

是不是感觉 2 和 3 有所矛盾呢?可以在后面的代码和结果中找答案。

默认优先级

先上代码来感受一下线程优先级的作用:

public class ThreadPriorityTest {
    class PrimeRun implements Runnable {
        public void run() {
            System.out.println(Thread.currentThread().getName() +"::"+
                    Thread.currentThread().getPriority());
            System.out.println(Thread.currentThread().getName() + " Run begin");
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName()+"::"+i);
            }
            System.out.println(Thread.currentThread().getName() + " Run end");
        }
    }

    public void test(){
        System.out.println(Thread.currentThread().getName()+" begin");
        Thread p4 = new Thread(new PrimeRun());
        Thread p6 = new Thread(new PrimeRun());
        p4.setName("P4");
        p6.setName("P6");
        p4.start();
        p6.start();
        System.out.println(Thread.currentThread().getName()+" end");
    }

    public static void main(String[] args) {
        new ThreadPriorityTest().test();
    }
}

在 PrimeRun 类的 run() 方法中, 只是对 0 到 10 进行输出, 前面加上线程名字以识别。没有对线程进行设置, 按以上分析的 init() 方法可知, 优先级继承于 ThreadPriorityTest 中的优先级, 没进行设置优先级默认为 5。 输出如下:

可以看到 p4 和 p6 的线程优先级都是 5, 输出是无序的, P4 和 P6 交叉输出, 因此每次的结果都不一样。

指定优先级

将线程中的优先级改一下, test() 函数变成如下:

public void test(){
    System.out.println(Thread.currentThread().getName()+" begin");
    Thread p4 = new Thread(new PrimeRun());
    Thread p6 = new Thread(new PrimeRun());
    p4.setName("P4");
    p4.setPriority(4);
    p6.setName("P6");
    p6.setPriority(6);
    p4.start();
    p6.start();
    System.out.println(Thread.currentThread().getName()+" end");
}

在运行之后的输出如下:

可以看到, P6 先于 P4 运行完。

注意事项

但是(一般 「但是」 后面的东西都要注意)

优先级和操作系统及虚拟机版本相关。

++优先级只是代表告知了 「线程调度器」该线程的重要度有多大。如果有大量线程都被堵塞,都在等候运

行,调试程序会首先运行具有最高优先级的那个线程。然而,这并不表示优先级较低的线程不会运行(换言之,不会因为存在优先级而导致死锁)。若线程的优先级较低,只不过表示它被准许运行的机会小一些而已。++

因此, 在实际的编码时, 认为高优先级一定先于低优先级的线程执行, 最后会出问题的。

优先级继承

而关于特点 2 和 3 的区别, 我们在第一次 test() 时, P4 和 P6 的优先级都是 5, 我们将函数改一下:

 public void test(){
    Thread.currentThread().setPriority(10);
    System.out.println(Thread.currentThread().getName()+" begin");
    Thread p4 = new Thread(new PrimeRun());
    Thread p6 = new Thread(new PrimeRun());
    p4.setName("P4");
    p6.setName("P6");
    p4.start();
    p6.start();
    System.out.println(Thread.currentThread().getName()+" end");
}

在创建 P4 和 P6 之前将当前线程的优先级设置为 10, 并在 run() 中去掉一些无关的输出, 最后输入如下:

原文地址:https://www.cnblogs.com/homejim/p/9527226.html

时间: 2024-10-24 12:44:58

Java 多线程(二)之 Thread 优先级的相关文章

从零开始学习Java多线程(二)

前面已经简单介绍进程和线程,为后续学习做铺垫.本文讨论多线程传参,Java多线程异常处理机制. 1. 多线程的参数传递 在传统开发过程中,我们习惯在调用函数时,将所需的参数传入其中,通过函数内部逻辑处理返回结果,大多情况下,整个过程均是由一条线程执行,排除运行不必要的的偶发性,似乎并不会出现意料之外的结果.而在多线程环境下,在使用线程时需要对线程进行一些必要的初始化,线程对这些数据进行处理后返回结果,由于线程的运行和结束并不可控,线程传参变得复杂起来,本文就以上问题介绍三种常用的传递参数方式.

java多线程(二)——用到的设计模式

接上篇:java多线程(一)http://www.cnblogs.com/ChaosJu/p/4528895.html java实现多线程的方式二,实现Runable接口用到设计模式——静态代理模式 一.代理模式 代理模式的定义 代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用. 代理模式不会改变原来的接口和行为,只是转由代理干某件事,代理可以控制原来的目标,例如:代理商,代理商只会卖东西,但并不会改变行为,不会制造

java 多线程2:Thread的实例方法

Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1.this.XXX() 和 线程对象实例.XXX() 这里要首先参考 多线程 Thread.currentThread().getName() ,对象实例.getName() 和 this.getName()区别 理解采用Thread继承实现线程的几种启动方式出现的问题 这种调用方式表示的线程是线程

java多线程之线程的优先级

在操作系统中,线程可以划分优先级,优先级较高的线程得到CPU资源较多,也就是CPU优先执行优先级较高的线程对象中的任务(其实并不是这样). 在java中,线程的优先级用setPriority()方法就行,线程的优先级分为1-10这10个等级,如果小于1或大于10,则抛出异常throw new IllegalArgumentException(),默认是5. public class MyThread1 extends Thread { @Override public void run() {

java 多线程3:Thread类中的静态方法

Thread类中的静态方法 Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程".为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作.下面来看一下Thread类中的静态方法: 1.currentThread() currentThread()方法返回的是对当前正在执行线程对象的引用.看一个重要的例子,然后得出结论: public class MyThread04 extends Thread { static { System.o

Java多线程(二) 多线程的锁机制

当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名Java的锁机制,阐述多线程下如何使用锁机制进行并发线程沟通. 1.并发下的程序异常 先看下下面两个代码,查看异常内容. 异常1:单例模式 1 package com.scl.thread; 2 3 public class SingletonException 4 { 5 public stati

java多线程二之线程同步的三种方法

java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Semaphore. 线程同步问题引入: 创建一个银行账户Account类,在创建并启动100个线程往同一个Account类实例里面添加一块钱.在没有使用上面三种方法的情况下: 代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

Java多线程——&lt;二&gt;将任务交给线程,线程声明及启动

一.任务和线程 <thinking in java>中专门有一小节中对线程和任务两个概念进行了具体的区分,这也恰好说明任务和线程是有区别的. 正如前文所提到的,任务只是一段代码,一段要达成你目的的代码,这段代码写在哪,怎么写其实无所谓,只是因为你希望java的多线程机制能够识别并调用你编写的任务,所以规定了Runnable接口,让你的任务来实现该接口,把你想做的工作在实现该接口的run方法中实现. 那么,已经定义了任务类,那任务和线程有什么关系呢? java的线程是用来驱动任务执行的,也就是说

java多线程(二)——锁机制synchronized(同步方法)

synchronized Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行.另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块.然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块. ——以上来源百度百科 一.方法内的变量为线程安全 “非线程安全”的问题