1.走近Java世界中的线程

一.基本概念

 进程是程序运行的实例。

 进程是程序向操作系统申请资源(如内存空间和文件句柄)的基本单位。线程是进程中可独立执行的最小单位。

 一个进程中可以包含多个线程。同一个进程中的所有线程共享该进程中的资源。

二.Java线程API简介

2-1 Thread

 start方法的返回并不代表相应的线程已经被启动,仅表明线程被提交给了线程调度器,线程什么时候启动由线程调度器决定。

 线程(Thread实例)的start方法只能够被调用一次,多次调用同一个Thread实例的start方法会导致其抛出IllegalThreadStateException异常。

 在Java平台,一个线程就是一个对象,对象的创建离不开内存空间的分配。创建一个线程与创建其他类型的Java对象不同的是,Java虚拟机会为每个线程分配调用栈(Call Stack)所需的内存空间。Java平台中的每个线程可能还有一个内核线程(具体与Java虚拟机的实现有关)与之对应。因此,创建线程对象比创建一个其他类型的对象成本要高一些。

  • 调用栈:用于跟踪Java代码(方法)间的调用关系以及Java代码对本地代码(Native Code,通常是C代码)的调用。

2-2 Runnable接口

 Runnable接口可以看作是任务的抽象,任务的处理逻辑就体现在run方法之中。

 Thread类实际上是Runnable接口的一个实现类。

2-3 线程属性

 线程的属性包括线程的编号(ID)、名称(Name)、线程类别(Daemon)和优先级(Priority)。

2-1 线程的属性
属 性 属性类型及用途 只读属性 重要注意事项
编号(ID)

类型:long。用于标识不同的线程。

不同的线程拥有不同的编号。

某个编号的线程运行结束后,该编号可能被后续创建的线程使用。

不同线程拥有不同编号的这种唯一性只在Java虚拟机的一次运行中有效。

该属性的值不适合用作某种唯一标识,特别是作为数据库中的唯一标识(如主键)。

名称(Name)

类型:String。面向人(而非机器)的一个属性,用于区分不同的线程。

默认值格式为:Thread-线程编号。

可以将不同线程的名称设为相同的值,但这不便于代码调试和问题定位。
线程类别(Daemon)

类型:boolean。true表示线程为守护线程,否则表示为用户线程。

该属性的值与相应线程的父线程的该属性值相同

该属性必须在相应的线程启动之前设置,即对setDaemon方法的调用必须在对start方法的调用之前,否则setDaemon方法会抛出IllegalThreadStateException异常。

负责一些关键任务处理的线程不适宜设置为守护线程。

优先级(Priority)

类型:int。本质是给线程调度器的提示,用于表示应用程序希望哪个线程能够优先得以运行。Java定义了1-10的10个优先级,默认值为5(表示普通优先级)。

对于一个具体的线程而言,其优先级的默认值与其父线程的优先级相等。

一般使用默认优先级即可。

不恰当地设置该属性值可能导致严重的问题(线程饥饿)。

 按照线程是否会阻止Java虚拟机进程(运行的Java程序)正常停止,将Java中的线程分为守护线程(Daemon Thread)和用户线程(User Thread)。用户线程会阻止Java虚拟机进程的正常停止,即一个Java虚拟机进程只有在其所有用户线程都运行结束的情况下才能正常停止。而守护线程则不会影响Java虚拟机进程的正常停止,即应用程序中有守护线程在运行也不影响Java虚拟机进程的正常停止。因此,守护线程通常用于执行一些重要性不是很高的任务,例如用于监视其他线程的运行情况。

  • 如果Java虚拟机进程是被强制停止的,比如在Linux系统下使用kill命令(kill -9 PID)强制终止一个Java虚拟机进程,那么即使是用户线程也无法阻止Java虚拟机的停止。

2-4 线程的生命周期状态

                             图 2-4-1 Java线程状态

 Java线程状态可以使用监控工具查看,也可以通过Thread.getState()调用来获取。Thread.getState的返回值类型Thread.State是一个枚举类型。Thread.State所定义的线程状态包括以下几种:

 NEW: 一个已创建而未启动(调用Thread.start())的线程处于该状态。由于一个线程只能被启动一次,因此一个线程只可能有一次处于该状态。

 RUNNABLE:该状态可以被看成一个复合状态。它包括两个子状态:READY和RUNNING。前者表示处于该状态的线程可以被线程调度器(Scheduler)进行调度而使之处于RUNNING状态。后者表示该状态的线程正在运行,即相应线程对象的run方法所对应的指令正在由处理器执行。执行Thread.yield()的线程,其状态可能会由RUNNING转换为READY。处于READY状态的线程也被称为活跃线程。

 BLOCKED:一个线程发起一个阻塞式I/O(Blocking I/O)操作后,或者申请一个由其他线程持有的独占资源(比如锁)时,相应的线程会处于该状态。处于BLOCKED状态的线程并不会占用处理器资源。当阻塞式I/O操作完成后,或者线程获得了其申请的资源,该线程的状态又可以转换为RUNNABLE(READY->RUNNING)。

 WAITING:一个线程执行了某些特定的方法之后就会处于这种等待其他线程执行另外一些特定操作的状态。

 TIMED_WAITING:该状态和WAITING类似,差别在于处于该状态的线程并非无限等待其他线程执行特定操作,而是处于带有时间限制的等待状态。当其他线程没有在指定时间内执行该线程所希望的操作时,该线程的状态自动转换为RUNNABLE(READY->RUNNING)。

 TERMINATED:已经执行结束的线程处于该状态。由于一个线程实例只能够被启动一次,因此一个线程也只可能有一次处于该状态。Thread.run()正常返回或者由于抛出异常而提前终止都会导致相应线程处于该状态。

  • 只有RUNNING状态会占用处理器资源。
posted @ 2023-01-01 12:23  certainTao  阅读(64)  评论(0编辑  收藏  举报