一、概念

  1、进程

  进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

  进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。

  进程的概念主要有两点:第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程

  2、线程

  线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组 成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个 进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程 在运行中呈现出间断性。线程也有就绪阻塞运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程

  线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程

  区分:进程是资源分配的最小单位,线程是CPU调度的最小单位。线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空 间,每个线程有自己的执行堆栈和程序计数器为其执行上下文.多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定,线程的运行中需要使用计算机的内存资源和CPU。

 二、Thread的API

  1、构造函数

  

  2、常用静态函数 

  static int activeCount()  返回当前线程的线程组中活动线程的数目。

  static Thread currentThread()  返回对当前正在执行的线程对象的引用。

  static boolean holdsLock(Object obj)  当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true

  static boolean interrupted()   测试当前线程是否已经中断。

  static void sleep(long millis)   在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

  static void sleep(long millis, int nanos)   在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

  static void yield()   暂停当前正在执行的线程对象,并执行其他线程。

  3、常用实例函数 

  long getId(); void setId();  get/set该线程的标识符。

  String getName(); void setName();  get/set该线程的名称。

  int getPriority(); void setPriority();  get/set该线程的优先级。

  boolean isDaemon(); void setDaemon();  get/set该线程是否为守护线程。

  boolean isAlive()   测试线程是否处于活动状态。

  boolean isInterrupted()   测试线程是否已经中断。

  void join()   等待该线程终止。

  void join(long millis)   等待该线程终止的时间最长为 millis 毫秒。

  void join(long millis, int nanos)   等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

  void run()   如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

  void start()   使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

  4、过时的函数

  void destroy() 
      该方法最初用于破坏该线程,但不作任何清除。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即使要实现,它也极有可能以 suspend() 方式被死锁。如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。如果另一个线程曾试图锁定该资源,则会出现死锁。这类死锁通常会证明它们自己是“冻结”的进程。

  void  suspend() 
  该方法已经遭到反对,因为它具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源。如果重新开始目标线程的线程想在调用 resume 之前锁定该监视器,则会发生死锁。这类死锁通常会证明自己是“冻结”的进程。

  void resume() 
  该方法只与 suspend() 一起使用,但 suspend() 已经遭到反对,因为它具有死锁倾向。

  void stop() 
  该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。stop 的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。如果目标线程等待很长时间(例如基于一个条件变量),则应使用 interrupt 方法来中断该等待。

  void stop(Throwable obj) 
  该方法具有固有的不安全性。有关详细信息,请参阅 stop()。 该方法的附加危险是它可用于生成目标线程未准备处理的异常(包括若没有该方法该线程不太可能抛出的已检查的异常)。 

  参考:http://www.apihome.cn/api/java/Thread.html

三、线程的状态流转 

  线程的状态如下:

  

  线程状态流转及其原因:

  

四、附加知识点

  1、interrupt()、interrupted() 和 isInterrupted()的区别

  interrupt方法用于中断线程,调用该方法的线程的状态为将被置为"中断"状态。

  interrupted 和 isInterrupted用于判断该线程是否处于中断状态;

  可以看一下两个方法的实现:  

public static boolean interrupted () {
    return currentThread().isInterrupted(true);
}
public boolean isInterrupted () {
    return isInterrupted(false);
}

  这两个方法有两个主要区别:

  • interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)

  • 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;
  再来看下这个函数:
  private native boolean isInterrupted(boolean ClearInterrupted);
  它是一个本地函数,参数代表是否要清除状态位。如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。  

  所以可以总结如下:interrupted是静态方法,返回的是当前线程的中断状态。例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

  参考:http://blog.csdn.net/z69183787/article/details/25076033

  2、线程优先级

  在Java中,线程的优先级分为1~10这10个等级,预置定义以下三个值:

  

  特性:

  1)继承性:A线程启动B线程,则B与A有相同的优先级;

  2)规则性:CPU会尽量把执行资源让给优先级比较高的线程;

  3)随机性:优先级高的线程并不总是比低优先级的线程先执行完;

  3、守护线程

  在Java中有两种线程,用户线程和守护线程。守护线程是一种特殊线程,当进程中不存在非守护线程时,守护线程会随着JVM一同结束工作,自动销毁,典型的守护线程就是垃圾回收线程。

  4、suspend() 和 resume() 被停用原因

  缺点1:独占

  在使用这两个方法时,很容易造成公共的同步资源的独占,是其他线程无法访问公共同步对象;需注意:PrintStream对象的println()方法是synchronized的,很容易被独占导致其他线程阻塞;

  缺点2:不同步

  很容易出现因为线程暂停而导致数据的不同步的情况;

  5、yield()、sleep() 和 wait() 的区别

  1)从来源来看:wait()来自于Object类,sleep()、yield()来自于Thread的静态函数;

  2)sleep()在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”,yield()也不会;而wait()方法在其他线程调用对象的notify或notifyAll方法前,当前线程保持等待,释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁;调用wait()或者notify()的方法必须拥有公共资源的锁,否则会抛出IllegalMonitorStateException异常;

  3)sleep()方法和yield()方法都是Thread类的静态方法,都会使当前处于运行状态的线程放弃CPU,把运行机会让给别的线程。两者的区别在于:

    a.sleep()方法会给其他线程运行的机会,不考虑其他线程的优先级,因此会给较低优先级线程一个运行的机会,yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会;

    b.当线程执行了sleep(long millis)方法,将转到阻塞状态,参数millis指定睡眠时间,当线程执行了yield()方法,将转到就绪状态;

    c.sleep()方法声明抛出InterruptedException异常,而yield()方法没有声明抛出任何异常。

posted on 2017-04-18 16:19  离不开水的鱼  阅读(190)  评论(0)    收藏  举报