软件开发架构师

Java的线程

java 93 2019-04-20 00:17

    一:Java的线程实现

    1:使用内核线程实现

       操作系统的内核线程由系统内核完成切换调度,把线程任务映射到各个处理器上。使用内核线程来实现Java线程,优点在于:内核负责了线程的调度,不用担心线程阻塞问题。  缺点是:各种线程操作都需要系统调用,代价较高。

    2:使用用户线程实现

       操作系统的用户线程建立在用户空间的线程库上,用户线程的操作都在用户态中完成,无需内核操作,快速而低消耗。缺点在于:需要自己处理线程的调度、阻塞问题。

    3:使用内核线程和用户线程来混合实现

       使用用户线程进行大规模的线程建立,内核线程提供调度和处理器映射功能。

 

        二:Java线程调度

       协同式调度:线程的执行时间由自己掌控,线程把自己的工作执行完了后,主动通知系统切换到另一个线程上。缺点:若发生线程阻塞将使程序一直阻塞在那里。所以现在一般不采用。

       抢占式调度:每个线程由系统来分配执行时间,时间片执行完了后系统负责切换线程,这样就不会发生一个线程阻塞导致整个程序阻塞的问题。Java目前使用的就是抢占式调度,并且作出了改进:给线程设置了10个优先级,“建议”系统在调度时优先执行优先级高的。

 

    三:线程的状态变换

       1. 新建状态(New):新创建了一个线程对象。
       2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
       3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
       4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
        (一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
        (二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
        (三)、其他阻塞:运行的线程执行sleep()join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

       注:等待阻塞会挂起,等待别人唤醒,时间可能会很久,所以要释放同步锁;睡眠或抢占或IO导致的阻塞,是不会长久的,很快又会重新使用,所以不会释放同步锁。

       注:只有就绪态才可以直接转换为运行态,新建、阻塞的恢复 都是切换回就绪态等待CPU调度才能切换到运行态。
       5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

文章评论