Java 并发 线程的优先级

Java 并发 线程的优先级

@author ixenos

低优先级线程的执行时刻



1.在任意时刻,当有多个线程处于可运行状态时,运行系统总是挑选一个优先级最高的线程执行,只有当线程停止、退出或者由于某些原因不执行的时候,低优先级的线程才可能被执行

2.两个优先级相同的线程同时等待执行时,那么运行系统会以round-robin的方式选择一个线程执行(即轮询调度,以该算法所定的)(Java的优先级策略是抢占式调度!)

3.被选中的线程可因为一下原因退出,而给其他线程执行的机会:

  1) 一个更高优先级的线程处于可运行状态(Runnable)

  2)线程主动退出(yield),或它的run方法结束

  3)在支持分时方式的系统上,分配给该线程的时间片结束

4.Java运行系统的线程调度算法是抢占式(preemptive)的,当更高优先级的线程出现并处于Runnable状态时,运行系统将选择高优先级的线程执行

5.例外地,当高优先级的线程处于阻塞状态且CPU处于空闲时,低优先级的线程也会被调度执行

 1 public class PriorityExample{
 2     public static void main(Strinig[] args){
 3         Thread a = new PThread("A");
 4         Thread b = new PThread("B");
 5         a.setPriority(7); //设置优先级
 6         a.setPriority(1);
 7     }
 8 }
 9
10 class PThread extends Thread{
11     public PThread(String n){
12         super(n);
13     }
14
15     public void run(){
16         for(int i=0; i<5000000; i++){
17             if(i%5000000 == 0){
18                 System.out.print(getName());
19             }
20         }
21     }
22 }

输出 AAAAAAAAABBBBBBBBB

利己线程



1.一般地,在线程中可以调用sleep方法,放弃当前线程对处理器的使用,从而使各个线程均有机会得到执行,但有时候线程可能不遵循这个规则!

1 public void run(){
2     for(int i=0; i<5000000; i++){
3         if(i%5000000 == 0){
4             System.out.print(getName());
5         }
6     }
7 }

2.for循环是一个紧密循环,一旦运行系统选择了有for循环体的线程执行,该线程就不会放弃对处理器的使用权,除非for循环自然终止或者该线程被一个有更高优先级的线程抢占,这样的线程称为利己线程

3.利己线程一般不引起问题,但有时会让其他的线程得到处理器使用权之前等待一段很长的时间

分时方式



1.为解决利己线程可能长时间占据CPU的问题,有些系统通过分时方式来限制利己线程的执行,如Windows2000或WindowsNT系统

2.在分时方式中,处理器的分配按照时间片来划分,对于那些具有相同最高优先级的多个线程,分时技术会交替地分配CPU时间片给他们执行,当时间片结束,即使该线程没有运行结束,也会让出CPU使用权

3.注释掉优先级设置后,输出变成了AAAAABBBBBAAABBB或者AABBAAAABBBBAABBA

 1 public class PriorityExample{
 2     public static void main(Strinig[] args){
 3         Thread a = new PThread("A");
 4         Thread b = new PThread("B");
 5         //a.setPriority(7); //设置优先级
 6         //a.setPriority(1);
 7     }
 8 }
 9
10 class PThread extends Thread{
11     public PThread(String n){
12         super(n);
13     }
14
15     public void run(){
16         for(int i=0; i<5000000; i++){
17             if(i%5000000 == 0){
18                 System.out.print(getName());
19             }
20         }
21     }
22 } 

而如果在另一个不支持分时技术的平台上运行程序,得到的输出结果可能是确定的! AAAAAAAAABBBBBBBBB

4.Java运行系统不实现分时,分时是和平台相关的,而有的平台不支持分时,在编写Java多线程程序的时候,不能过分依赖分时技术来保证各个线程都有公平的执行机会!通常应编写那种可以主动放弃处理器使用权的程序,同时一个线程也可以调用yield方法主动放弃对处理器的使用权

  注意:使用yield只能给同优先级的线程提供执行机会,如果没有同优先级的线程处于可运行状态,yield方法将被忽略!

时间: 2024-08-09 19:13:15

Java 并发 线程的优先级的相关文章

Java 并发 线程属性

Java 并发 线程属性 @author ixenos 线程优先级 1.每当线程调度器有机会选择新线程时,首先选择具有较高优先级的线程 2.默认情况下,一个线程继承它的父线程的优先级 当在一个运行的线程A里,创建另一个线程B的时候,那么A是父线程,B是子线程.当在一个运行的线程A里,创建线程B,然后又创建了线程C,这时候虽然B比C创建早,可是B并不是C的父线程,而A是B和C的父线程. 3.线程的优先级高度依赖于系统,当虚拟机依赖于宿主机平台的线程实现机制时,Java线程的优先级被映射到宿主机平台

Java 并发 线程的生命周期

Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a)     New 新建 b)     Runnable 可运行 c)     Running 运行 (调用getState()时显示为Runnable) d)     Blocked 阻塞 i.          I/O阻塞 (不释放锁) I/O操作完成解除阻塞,进入Runnable状态 ii.          同步阻塞(不释放锁) 运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会

Java 并发 线程同步

Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大多数实际的多线程应用中,两个或两个以上的线程需要共享对同一数据的存取,这将产生同步问题(可见性和同步性的丢失) 比如两个线程同时执行指令account[to] += amount,这不是原子操作,可能被处理如下: a)将account[to]加载到寄存器 b)增加amount c)将结果写回acco

java并发-线程饥饿死锁测试

线程饥饿死锁 <Java并发编程实践>中对线程饥饿死锁的解释是这样的:在使用线程池执行任务时,如果任务依赖于其他任务,那么就可能产生死锁问题.在单线程的Executor中,若果一个任务将另一个任务提交到同一个Executor,并且等待这个被提交的任务的结果,那么这必定会导致死锁.第一个任务在工作队列中,并等待第二个任务的结果:而第二个任务则处于等待队列中,等待第一个任务执行完成后被执行.这就是典型的线程饥饿死锁.即使是在多线程的Executor中,如果提交到Executor中的任务之间相互依赖

java并发-线程

前言 近来时间比较充裕,正好又看了一遍<实战java高并发程序设计>,故而对java并发一些知识进行下总结,算是温故而知新吧. 一,线程基础 1,新建线程 一般有两种实现方式实现Runnable接口或继承Thread类(Thread类本身也是实现Runnable接口) public class Test { public static void main(String[] args) throws Exception { Thread t1=new TestThread(); Thread t

Java并发——线程间的等待与通知

前言: 前面讲完了一些并发编程的原理,现在我们要来学习的是线程之间的协作.通俗来说就是,当前线程在某个条件下需要等待,不需要使用太多系统资源.在某个条件下我们需要去唤醒它,分配给它一定的系统资源,让它继续工作.这样能更好的节约资源. 一.Object的wait()与notify() 基本概念: 一个线程因执行目标动作的条件未能满足而被要求暂停就是wait,而一个线程满足执行目标动作的条件之后唤醒被暂停的线程就是notify. 基本模板: synchronized (obj){ //保护条件不成立

Java并发 - 线程池的使用

线程池的使用 一丶什么是线程池 为了避免系统频繁的创建和销毁线程, 需要将创建好的线程"存储"管理起来复用, 可以形象的理解为"池子", 当需要线程时, 则向线程池申请一个线程, 用完之后,并不会销毁, 而是将线程归还给线程池, 减少线程的创建和销毁. 二丶为什么需要线程池 1) 多线程虽然可以提高系统性能,但如果数量不加以控制, 频繁的创建和销毁线程, 会消耗系统性能 2) 线程会占用内存, 如果过多创建线程, 会出现内存溢出的问题 因此, 在实际生产环境中, 线

Java 并发 – 线程安全?

线程安全的定义常常让人迷惑,搜索引擎会发现无数定义,比如: 多个线程同时执行也能正确工作就是线程安全的代码 多个线程同时执行能以正确的方式操纵共享数据就是线程安全的代码. 而且还有很多类似的定义 你是否认为这种定义实际上没有任何意义而且还让人更加迷惑?虽然这些定义没错,但事实是他们没有提供任何实际的帮助或观点.我们如何区分线程安全类和不安全类?我们所谓的"安全"是什么意思? 线程安全的正确性是什么? 线程安全的任何合理定义的核心是正确性的概念.因此,在了解线程安全之前,我们首先应该理解

Java并发——线程间通信与同步技术

传统的线程间通信与同步技术为Object上的wait().notify().notifyAll()等方法,Java在显示锁上增加了Condition对象,该对象也可以实现线程间通信与同步.本文会介绍有界缓存的概念与实现,在一步步实现有界缓存的过程中引入线程间通信与同步技术的必要性.首先先介绍一个有界缓存的抽象基类,所有具体实现都将继承自这个抽象基类: public abstract class BaseBoundedBuffer<V> { private final V[] buf; priv