zoukankan      html  css  js  c++  java
  • 多线程

    1.Java线程的运行机制

      在Java 虚拟机进程中,执行程序代码的任务是由线程来完成的。每个线程都有一个独立的程序计数器和方法调用栈(methodinvocationstack)

      1.程序计数器: 也称为PC 寄存器,当线程执行一个方法时,程序计数器指向方法区中下一条要执行的字节码指令。

      2.方法调用栈:简称方法栈,用来跟踪线程运行中一系列的方法调用过程,栈中的元素称为栈帧。

      每当线程调用一个方法的时候,就会向方法栈压入一个新帧。帧用来存储方法的参数、局部变量和运算过程中的临时数据。

      栈帧由以下3 部分组成。

      3.局部变量区: 存放局部变量和方法参数。

      4.操作数栈: 是线程的工作区,用来存放运算过程中生成的临时数据。

      5.栈数据区:为线程执行指令提供相关的信息,包括如何定位到位于堆区和方法区的特定数据,以及如何正常退出方法或者异常中断方法。

    示例:

    当主线程执行main0方法时,会创建两个Machine 对象,然后启动两个Machine线程,接着主线程开始执行第一个Machine 对象的run0方法。在Java虚拟机中有三个

    线程并发执行Machine 对象的run0方法。在三个线程各自的方法栈中都有代表run0方法的栈帧,在这个帧中存放了局部变量a,可见每个线程都拥有自己的局部变量a,

    它们都分别从0增加到50。

     2.线程的状态转换

       1.线程的状态转换图

     

    2.线程的几种状态

      1.新建状态(New)

        用New语句创建的线程对象处于新建状态此时他和其他Java对象一样仅仅在堆区中分配的内存。

      2.就绪状态(Runnable)当一个线程对象创建后,其他线程调用它的tart0方法,该线程就进入就绪状态,

        Java 虚拟机会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中,等持获得CPU的使用权。

      3.运行状态(Running)

        处于这个状态的线程古用CPU,执行程序代码。在并发运行环境中,如果计算机只有一个CPU,那么任何时刻只会有一个线程处于这个状态。如果计算机有多个CPU,

        那么同一时刻可以让几个线程占用不同的CPU,使它们都处于运行状态,只有处于就绪状态的线程才有机会转到运行状态。

      4.阻塞状态(Blocked)

        阳塞状态是指线程因为某些原因放弃CPU,暂时停止运行,当线程处于阳塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才有机会转到运行状态。

        阳塞状态可分为以下3种。

        ★位于对象等特池中的阻塞状态(Blockedinobjet'saitpo 当线程处于运行状态时,如果执行了某个对象的wait方法,Java虚拟机就会把线程放到这

        个对象的等待池中,参见本章第139节(线程通信)。

        ★位于对象锁池中的阻塞状态(Blockdiojgctesloco 当线程处于运行状态,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他线程

        占用,Java虚拟机就会把这个线程放到这个对象的锁池中,参见本幸第138节(线程的同步)。

        ★其他阳塞状态(OtherwiseBlocked)当前线程执行了seep0方法,或者调用了其他线程的join0方法,或者发出了IO请求时,就会进入这个状态。

       死亡状态(Dead)

        当线程退出run(O方法时,就进入死亡状态,该线程结束生命周期。线程有可能是正常执行完run(方法而退出,也有可能是遇到异常而退出。不管线程正常结束还是异

        常结束,都不会对其他线程造成影响。例如在例程13-9 中,Machine 线程在运行时为抛出RuntimeException 异常而结束,此时主线程继续正常运行直至结束。 

       

        当一个线程执行Systmoutprinin或者Systeminread0方法时,就会发出个IO请求,该线程放弃CPU,进入阴寨状态,直到1O处理完毕,该线程才会恢复运行。

        例如在例程13-8的Machine类中,主线程在启动个Mactine线程后,就等待用户的标准输入。主线程进入阻塞状态,Machine 线程占用CPU,继续运行。直到用户输入

        数据,主线程才会恢复运行。

     3.线程调度

          计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令。所谓多线程的并发运行,其实是指从宏观上看,各个

      线程轮流获得CPU的使用权,分别执行各自的任务。在可运行池中,会有多个处于就绪状态的线程在等待CPU,Java 虚拟机的一项任务就是负责线程的调度。线程的调度

      是指按照特定的机制为多个线程分配CPU 的使用权。有两种调度模型: 分时调度模型和抢占式调度模型。

          分时调度模型是指让所有线程轮流获得CPU 的使用权,并且平均分配每个线程占用CPU 的时间片。

          Java 虚拟机采用抢占式调度模型,是指优先让可运行池中优先级高的线程占用CPU,如果可运行池中线程的优先级相,那么就随机选择一个线程,使其占用CPU。

      处于运行状态的线程会一直运行,直至它不得不放弃CPU。一个线程会因为以下原因而放弃CPU。

        ★Java虚拟机让当前线程暂时放弃CPU,转到就绪状态,使其他线程获得运行机会。

        ★当前线程因为某些原因而进入阻塞状态。

        ★线程运行结束。

      值得注意的是,线程的调度不是跨平台的,它不仅取决于Java虚拟机,还依赖于操作系统。在某些操作系统中,只要运行中的线程没有遇到阻塞,就不会放弃CPU;

      在某些操作系统中,即使运行中的线程没有遇到阻塞,也会在运行一段时间后放弃CPU,给其他线程运行的机会。

      Java 线程的调度不是分时的,同时启动多个线程后,不能保证各个线程轮流获得均等的CPU 时间片。例程13-10 (Machine.java) 可以证明这一一点。

      线程睡眠:Thread.sleep( )方法

        当一个线程在运行中执行了sleep(方法时,它就会放弃CPU,转到阻塞状态。下面对13.4 节开头的例程13-10的Machine 类的run(方法做如下修改,使线程执行完一

        次循环时,就睡眠100毫秒。

      线程让步: Thead.yield0方法

        当线程在运行中执行了Thread类的yield0静态方法,如果此时具有相同优先级的其他线程处于就绪状态,那么yield0方法将把当前运行的线程放到可运行池中并使另

        个线程运行。如果没有相同优先级的可运行进程,则yield(方法什么都不做。下面对13.4 节开头的例程13-10的run0方法做如下修改,使线程在执行完一次循

        环后,就执行yield()方法。

      等待其他线程结束: join()

        当前运行的线程可以调用另一个线程的join0方法,当前运行的线程将转到阻塞状态,直至另一个线程运行结束,它才会恢复运行。

  • 相关阅读:
    win8 app scrollviewer ZoomMode
    win8 metro app 不支持 trigger
    WinRT Convert Stream to BitmapImage
    Java深度历险(二)——Java类的加载、链接和初始化(收藏)
    简单的触发器实现
    Java深度历险(一)——Java字节代码的操纵(收藏)
    借用网上大神的一些知识,html5 video 视频播放都兼容(Android,iOS,电脑)
    还原或删除sql server 2008数据库时,经常烩出现: “因为数据库正在使用,所以无法获得对数据库的独占访问权”,终解决方案
    调研《构建之法》指导下的历届作品
    Hibernate 学习笔记一
  • 原文地址:https://www.cnblogs.com/wxl941549541/p/8544782.html
Copyright © 2011-2022 走看看