zoukankan      html  css  js  c++  java
  • JavaSE 多线程(一)

    1. 线程和多线程

    1.1 线程的概念

    提到线程,首先要从 “进程” 开始讲起。对于一般程序而言,其结构大部分都可以划分为一个入口、一个出口和一个顺次执行的语句序列。在程序投入运行时,系统从程序入口开始按语句的顺序(其中包括顺序、分支和循环)完成相应指令直至结尾,从出口退出,同时整个程序结束。这样的语句结构称为进程,它是程序的一次动态执行,对应了从代码加载、执行至执行完毕的一个完整过程;或者说,进程就是程序在处理机中的一次运行。需要特别明确的是,在这样的一个结构中,不仅包括了程序代码,同时也包括了系统资源的概念。也就是说,一个进程既包括其所要执行的指令,也包括了执行指令所需的任何系统资源,如CPU、内存空间、I/O端口等,不同进程所占用的系统资源相对独立。

    线程 是进程执行过程中产生的多条执行线索,是比进程单位更小的执行单位,在形式上同进程十分相似————都是用一个顺序执行的语句序列来完成特定的功能。不同的是,它没有入口,也没有出口,因此其自身不能自动运行,而必须栖身于某一进程之中,由进程触发执行。而且在系统资源的使用上,属于同一进程的所有线程共享该进程的系统资源,但是线程之间切换的速度比进程切换要快得多。

    Java 类库中的类 java.lang.Thread 允许创建这样的线程,并可控制所创建的线程。

    1.2 线程的结构

    在 Java 中,线程可以认为是由三部分组成的:

    • 虚拟 CPU,封装在 java.lang.Thread 类中,它控制着整个线程的运行。

    • 执行的代码,传递给 Thread 类,由 Thread 类控制顺序执行。

    • 处理的数据,传递给 Thread 类,是在代码执行过程中所要处理的数据。

    在 Java 中,虚拟 CPU 体现于 Thread 类中。当一个线程被构造时,它由构造方法参数、执行代码、操作数据来初始化。应该特别注意的时,这三方面是各自独立的。一个线程所执行的代码与其他线程可以相同,也可以不同;一个线程访问的数据与其他线程可以相同,也可以不同。

    多线程的优势体现在以下几个方面:

    • 多线程编程简单,效率高。使用多线程可以在线程间直接共享数据和资源,而多线程之间不能做到这一点。

    • 适合于开发服务程序,如 Web 服务、聊天服务等。

    • 适合于开发有多种交互接口的程序,如聊天程序的客户端、网络下载工具。

    • 适合于有人机交互又有计算量的程序,如字处理程序Word、Excel等。

    2. 线程的状态

    Java 的线程是通过 Java 软件包 java.lang 中定义的类 Thread 来实现的。当生成一个 Thread 类的对象之后,是产生了一个线程。通过该对象实例,可以启动线程、终止线程,或者暂时挂起线程等。

    Thread 类本身只是线程的虚拟 CPU,线程所执行的代码(或者说线程所要完成的工作)是通过方法 run()(包含在一个特定的对象中)完成的,方法 run() 称为线程体。实现线程体的特定对象是在初始化线程时传递给线程的。

    在一个线程被建立并完成初始化以后,Java 的运行时系统自动调用 run() 方法,正是通过 run() 方法才使得建立线程的目的得以实现。

    线程一共有 4 中状态:新建(new)、可运行状态(runnable)、死亡(dead)及阻塞(blocked),如图所示:

    (1)新建

    线程对象刚刚创建,还没有启动,处于不可运行状态,如:

    Thread thread = new Thread("Test");
    

    此时线程 thread 处于新建状态,但已有了相应的内存空间以及其他资源。

    (2)可运行状态(runnable)

    此时的线程已经启动,处于线程的 run() 方法之中。这种情况下线程可能正在运行,也可能没有运行,只要 CPU 一空闲,马上就会运行。可以运行但并没在运行的线程都排在一个队列之中,这个队列称为就绪队列。

    调用线程 start() 方法可使线程处于 “可运行” 状态,如:

    thread.start();
    

    (3)死亡(dead)

    线程死亡的原因有两个:一是 run() 方法中最后一个语句执行完毕;二是当线程遇到异常退出时便进入了死亡状态。

    (4)阻塞(blocked)

    一个正在执行的线程因特殊原因被暂停执行,就进入阻塞状态。阻塞时线程不能进入就绪队列排队,必须等到引起阻塞的原因消除,才可重新进入队列排队。

    引起阻塞的原因有很多,不同原因要用不同的方法解除。如 sleep() 和 wait() 就是两个常用的引起阻塞的方法。

    (5)中断线程

    当 run() 执行结束返回时,线程自动终止。

    在程序中常常调用 interrupt() 来终止线程。interrupt() 不仅可中断正在运行的线程,而且也能中断处于 blocked 状态的线程,此时 interrupt() 会抛出一个 InterruptedException 异常。

    Java 提供了几个用于测试线程是否被中断的方法:

    • void interrupt() ————向一个线程发送一个中断请求,同时把这个线程的 “interrupted” 状态置为 true。若该线程处于 “blocked” 状态,会抛出一个 InterruptedException 异常。

    • static boolean interrupted() ————检测当前线程是否已被中断,并重置状态 “interrupted” 值。即如果连续两次调用该方法,则第二次调用将返回 false。

    • boolean isInterrupted ————检测当前线程是否已被中断,不改变状态 “interrupted” 值。

  • 相关阅读:
    几款JS地图插件比较
    Objective-C ,ios,iphone开发基础:多个视图(view)之间的切换2,使用导航栏控制,以及视图之间传值。
    学习嵌入式—导火线
    Linux MySQL 5.1源码安装
    QT 一些非常常用的操作
    QT 下把编辑框内的中文字符转换为 char*
    delphi datasnap 心跳包
    ddd
    Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)
    Python基础-输入输出(IO)
  • 原文地址:https://www.cnblogs.com/john1015/p/13938653.html
Copyright © 2011-2022 走看看