线程的调度

状态图:

RUNNABLE:当需要新起一个线程来执行某个子任务时,就创建了一个线程。但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源,在前面的JVM内存区域划分一篇博文中知道程序计数器、Java栈、本地方法栈都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。

RUNNING:当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

BLOCK:OTHER:sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。

yield方法:调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。

-- 摘自:Java并发编程:Thread类的使用   感谢!!!

线程的调度

调度图:

 

线程的调度

obj.join():是指主线程等待子线程的终止,也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。
(为什么要用到join()方法:在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,
  但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束)

调用obj的wait(), notify()方法前,必须获得obj锁

描述线程的状态是用一个枚举类型来描述的,严格来讲一个线程有六种状态(具体查看Thread类的源代码),分别是六个枚举值:NEW(新建状态), RUNNABLE(运行状态), BLOCKED(锁池状态),TIMED_WAITING(定时等待状态), WAITING(等待状态), TERMINATED(终止状态),只不过人们平时理解的时候经常会增加阻塞状态,可运行状态,还有挂起状态。
 

如果是双核系统,那么同一时间点会有 2 条线程处于 Running 状态但是,当线程数大于处理器数时,依然会是多条线程在同一个 CPU 上轮换执行 

 

***************************************************************虚假唤醒*************************************************************************

由于莫名其妙的原因线程有可能在没有调用过notify()和notifyAll()的情况下醒来,这就是所谓的虚假唤醒。为了防止假唤醒,保存信号的成员变量将在一个while循环里接受检查而不是在if表达式里,这样的一个while循环叫做自旋

while(条件不满足){ 
    this.wait();
} 

而不是: 
if(条件不满足){ 
    this.wait();
}  

*******************************************经典例子听说是*************************************************************************************

/*
 * 但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,
 * JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。
 * 打印出  10A、10B、10C、9A、9B、9C、8A、8B、8C、7A、7B、7C、6A、6B、6C、5A、5B、5C、4A、4B、4C、3A、3B、3C、2A、2B、2C、1A、1B、1C、
 */
public class Main implements Runnable {     
    
    private String name;     
    private Object prev;    // c a b
    private Object self;    // a b c 
    
    private Main(String name, Object prev, Object self) {     
        this.name = name;     
        this.prev = prev;     
        this.self = self;     
    }     
    
    @Override    
    public void run() {     
        int count = 10;     
        while (count > 0) {   
            System.out.print(count);
            // (1)线程pa获取了c对象锁,此时pb,pc线程处于BLOCKED:SYNCHRONIZED状态 
            // (7)线程pb进来,获取了a对象锁,此时pa线程处于对象c的等待队列,pc线程处于BLOCKED:SYNCHRONIZED状态
            // (13)线程pc进来,获取了b对象锁(pa在对象c的等待队列,pb在对象a的等待队列)
            // (19)只有线程pa不在等待队列(此刻pb在对象a的等待队列,pc在对象b的等待队列)
            synchronized (prev) {   
                // (2)线程pa获取了a对象锁
                // (8)线程pb获取b对象锁
                // (14)线程pc获取c对象锁
                // (20).......
                synchronized (self) {     
                    // (3)打印出A
                    // (9)打印出B
                    // (15)打印出C
                    System.out.print(name+"、"); 
                    // (4)count变9
                    // (10)count变8
                    // (16)count变7
                    count--;    
                    // (5)线程pa调用了对象a的notify()方法,唤醒从对象a的等待队列其中一个的线程(这个时候对象a等待队列实际上是没有线程的)到BLOCKED:SYNCHRONIZED(此时c对象锁还被线程pa控制住)
                    // (11)线程pb调用了对象b的notify()方法,唤醒从对象b的等待队列其中一个的线程(这个时候对象b等待队列上实际上是没有线程的,对象c等待队列上的线程只有pa)到BLOCKED:SYNCHRONIZED(此时a对象锁还被pb控制住)
                    // (17)线程pc调用了对象c的notify()方法,唤醒从对象c的等待队列其中一个的线程(pa在对象c的等待队列,pb在对象a的等待队列)(所以对象c的等待队列的线程pa被唤醒了)
                    // (21)线程pa调用了对象a的notify()方法,唤醒从对象a的等待队列其中一个的线程(唤醒线程pb)(此时线程pc在对象b的等待队列)
                    self.notify();     
                }  // self变量对象锁被释放   
                try {     
                    // (6)线程pa调用了c对象的wait方法,pa释放c对象锁,并进入对象c的等待队列中(此时线程pb,bc争夺c对象锁了)(一定一定要知道,synchronized(){}语句块执行结束,对象锁才释放的)
                    // (12)线程pb调用了对象a的wait方法,pb释放a对象锁,并进入a对象锁的等待队列(pa还在对象c的等待队列,此刻pb在对象a的等待队列)
                    // (18)线程pc释放b对象锁(此刻pb在对象a的等待队列,pc在对象b的等待队列)(所以对象c的等待队列的线程pa被唤醒了,17步被释放了)
                    // (22)线程pa释放锁c,进入对象c的等待队列(线程pa在对象c的等待队列中,pc在b的等待队列中,在a等待队列的线程pb在21步被释放了)
                    prev.wait(); 
                } catch (InterruptedException e) {     
                    e.printStackTrace();     
                }   
            } // prev  变量对象锁被释放
        }     
    }     
    
    public static void main(String[] args) throws Exception {     
        Object a = new Object();     
        Object b = new Object();     
        Object c = new Object();     
        Main pa = new Main("A", c, a);     
        Main pb = new Main("B", a, b);     
        Main pc = new Main("C", b, c);     
             
             
        new Thread(pa).start();  
        Thread.sleep(100);  //确保按顺序A、B、C执行  
        new Thread(pb).start();  
        Thread.sleep(100);    
        new Thread(pc).start();     
        Thread.sleep(100);    
   }     
}

 

欧巴