线程的优先级
在操作系统中,线程可以划分优先级,优先级较 高的线程得到 CPU 资源较多,也就是CPU优先执行优 先级较高的线程对象中的任务,其实就是让高优先级 的线程获得更多的 CPU时间片。 设置线程优先级有助于 “ 线程规划器 ”确定在下一 次选择哪一个线程来优先执行。
设置线程的优先级使用setPriority()方法
/**
* Changes the priority of this thread.
* <p>
* First the <code>checkAccess</code> method of this thread is called
* with no arguments. This may result in throwing a
* <code>SecurityException</code>.
* <p>
* Otherwise, the priority of this thread is set to the smaller of
* the specified <code>newPriority</code> and the maximum permitted
* priority of the thread's thread group.
*
* @param newPriority priority to set this thread to
* @exception IllegalArgumentException If the priority is not in the
* range <code>MIN_PRIORITY</code> to
* <code>MAX_PRIORITY</code>.
* @exception SecurityException if the current thread cannot modify
* this thread.
* @see #getPriority
* @see #checkAccess()
* @see #getThreadGroup()
* @see #MAX_PRIORITY
* @see #MIN_PRIORITY
* @see ThreadGroup#getMaxPriority()
*/
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);
}
}
线程优先级等级1~10
在 Java 中,线程的优先级分为 1 ~ 10 共 10个等级, 如果优先级小于 1 或大于 10 ,则 JDK 抛出异常throw new IllegalArgumentException() 。
预置定义优先级的值
JDK使用3个常量来预置定义优先级的值
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
线程优先级的继承特性
在 Java 中,线程的优先级具有继承性,例如, A线程启 动 B 线程,则 B 线程的优先级与 A 线程是一样的。
MyThread1.java
package test1_14;
public class MyThread1 extends Thread {
@Override
public void run() {
System.out.println("MyThread1 run priority=" + this.getPriority());
MyThread2 thread2 = new MyThread2();
thread2.start();
}
}
MyThread2.java
package test1_14;
public class MyThread2 extends Thread {
@Override
public void run() {
System.out.println("MyThread2 run priority=" + this.getPriority());
}
}
Run.java
package test1_14;
public class Run {
public static void main(String[] args) {
System.out.println("main thread begin priority=" + Thread.currentThread().getPriority());
// Thread.currentThread().setPriority(6);
System.out.println("main thread end priority=" + Thread.currentThread().getPriority());
MyThread1 thread1 = new MyThread1();
thread1.start();
}
}
运行结果
优先级被继承
去掉以下注释的运行结果
// Thread.currentThread().setPriority(6);
优先级被更改再继续继承
优先级的规律性
虽然使用 setPriority()方法可以设置线程的优先级,但还没有看到设置优先级所带来的效果。
MyThread1.java
package test1_14.test1;
import java.util.Random;
public class MyThread1 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
long addResult = 0;
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 50000; i++) {
Random random = new Random();
random.nextInt();
addResult = addResult + i;
}
}
long endTime = System.currentTimeMillis();
System.out.println("★★★★★thread 1 use time=" + (endTime - beginTime));
}
}
MyThread2.java
package test1_14.test1;
import java.util.Random;
public class MyThread2 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
long addResult = 0;
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 50000; i++) {
Random random = new Random();
random.nextInt();
addResult = addResult + i;
}
}
long endTime = System.currentTimeMillis();
System.out.println("☆☆☆☆☆thread 2 use time=" + (endTime - beginTime));
}
}
Run.java
package test1_14.test1;
public class Run {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
MyThread1 thread1 = new MyThread1();
thread1.setPriority(10);
thread1.start();
MyThread2 thread2 = new MyThread2();
thread2.setPriority(1);
thread2.start();
}
}
}
输出结果
可以发现,高优先级的线程总是大部分先执行 完,但不代表高优先级的线程全部先执行完。另外,并不是 MyThread1 线程先被 main线程调用就先执行完,出现这种结果是 因为 MyThread1 线程的优先级是最高级别10。当线程优先级的等 级差距很大时,谁先执行完和代码的调用顺序无关
为了验证这 个结论,修改Run.java代码
package test1_14.test2;
import test1_14.test1.MyThread1;
import test1_14.test1.MyThread2;
public class Run {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
MyThread1 thread1 = new MyThread1();
thread1.setPriority(1);
thread1.start();
MyThread2 thread2 = new MyThread2();
thread2.setPriority(10);
thread2.start();
}
}
}
输出结果
大部分thread2先执行完,这就验证线 程的优先级与代码执行顺序无关,出现这种结果是因为 MyThread2的优先级是最高的,说明线程的优先级具有一定的规 律性,即 CPU 尽量将执行资源让给优先级比较高的线程。
优先级的随机性
前面案例介绍了线程具有优先级,优先级高的线程往往优先执行完,但这个结果不是绝对的,因为线程的优先级还具有 “随 机性 ” ,即优先级较高的线程不一定每一次都先执行完。
为了让结果体现 “ 随机性 ”,将两个线程的优先级分别设置为 5 、 6 ,让优先级接近一些。
MyThread1.java
package test1_14.test3;
import java.util.Random;
public class MyThread1 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
Random random = new Random();
random.nextInt();
}
long endTime = System.currentTimeMillis();
System.out.println("★★★★★thread 1 use time=" + (endTime - beginTime));
}
}
MyThread2.java
package test1_14.test3;
import java.util.Random;
public class MyThread2 extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
Random random = new Random();
random.nextInt();
}
long endTime = System.currentTimeMillis();
System.out.println("☆☆☆☆☆thread 2 use time=" + (endTime - beginTime));
}
}
Run.java
package test1_14.test3;
public class Run {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
MyThread1 thread1 = new MyThread1();
thread1.setPriority(5);
thread1.start();
MyThread2 thread2 = new MyThread2();
thread2.setPriority(6);
thread2.start();
}
}
}
运行结果
交错执行完
根据此案例可以得出一个结论,优先级较高的线程并不一定 每一次都先执行完run()方法中的任务,也就是线程优先级与输出 顺序无关,这两者并没有依赖关系,它们具有不确定性、随机 性。
优先级对线程运行速度的影响
Run.java
package test1_14.test4;
public class Run {
public static void main(String[] args) {
try {
ThreadA a = new ThreadA();
a.setPriority(Thread.NORM_PRIORITY - 3);
a.start();
ThreadB b = new ThreadB();
b.setPriority(Thread.NORM_PRIORITY + 3);
b.start();
Thread.sleep(20000);
a.stop();
b.stop();
System.out.println("a=" + a.getCount());
System.out.println("b=" + b.getCount());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果
优先级高的运行得快