线程讲解(一)

  • Post author:
  • Post category:其他




线程说明

跟进程比较,线程的特点:

  • 线程本身不能单独运行,它必须在一个程序中运行.
  • 线程是程序的内部控制流,一个进程在执行过程中,为了同时完成多个操作,可以创建多个线程,形成多条执行线索.每个线程有自己的堆栈、自己的程序设计器和自己的局部变量.
  • 每个进程都有一段专用的内存区域.而同一个进程的各线程间可以共享相同的内存空间(代码空间和数据空间),并且利这些共享内存来实现数据交换、实施通信以及必要的同步工作.

线程是程序中的一个执行流,一个执行流是由CPU运行程序代码并操作程序的数据形成的.JAVA 中的线程模型就是一个CPU、程序代码和数据的封装体.线程在JAVA 中是由 java.lang.Thread 类来定义和描述的,程序中的线程都是 Thread 的实例.



线程的创建

JAVA 提供了一下两创建线程的方法:

  • 继承类 Thread.定义一个类,作为类 Thread 的子类,在该类上重写方法

    run()

    .
  • 实现 Runnable 接口.定义一个类,实现接口 Runnable,在该类上重写方法

    run()

    .



继承 Thread 类

方法

run()

是线程在运行时所要执行的动作,但是在执行线程过程中,并不是直接调用该方法,而是在由该类创建实例对象后,通过方法

start()

来启动线程.



实现 Runnable 接口

接口 Runnable 只有一个抽象方法

run()

,在实现该接口的类中需要重写该方法.

在线程运行时,实现了接口 Runnable 的对象需要由类 Thread 封装为线程实例,类 Thread 的构造方法可以接受接口 Runnable 的实例,然后线程实例通过

start()

方法启动线程.



两种方法比较

两种创建线程的方法有所区别,各有利弊.

  • 使用继承类 Thread 的方法相对简单,比较直观,但是由于 JAVA 语言是单继承机制,使得一个类继承了类 Thread 之后不能再继承其他类.
  • 通过实现 Runnable 接口的方法来创建线程时,虽然在生成线程实例时需要再通过 Thread 实例对 Runnable 实例进行封装;但定义时该类可以再继承其他类.

    Thread 类不支持线程重用.在处理多任务时,通常会创建多个线程,让一个线程执行一个任务.其实也可以创建几个线程,然后重用这些线程执行任务,相关可以学习线程池.



线程的属性

线程本身有一些特有的属性,例如:线程标识符、线程名以及线程间的优先级属性等.通过这些属性,可以用来识别一个线程、了解线程的状态、控制线程的优先权等.



线程标识符

该属性为每一个线程存储了唯一的一个标识符,通过线程标识符,可以对线程进行区分.使用方法getId().

thread:

this.getId()


Runnable:

Thread.currentThread().getId()



线程名

每个线程默认有一个名字,默认的名字采用 Thread-1,Thread-2…形式;也可以对创建的线程设置线程名.通过

getName()

可以获取线程名.



线程的状态

一个线程从创建、运行到终止称为一个生命周期.线程在其生命周期中要经历创建、就绪、运行、阻塞和终止5中状态.通过

getState()

获取运行状态.



创建 New

当一个 Thread 类或其子类使用 new 关键词声明一个对象实例时,此时线程处于创建的状态.处于创建状态的线程有自己的内存空间,但是线程还没有运行.



就绪 Runnable

处于创建状态的线程通过调用

start()

方法启动后,线程进入就绪状态.这时的线程就已经拥有了运行所需的所有条件,将进入线程队列等待CPU调度.由于还没有获取到CPU的时间片,所以不会立即执行.



运行 Running

当处于就绪状态的线程被调度,并获得CPU资源时,便进入运行状态.

  • 运行状态的线程执行

    Run()

    方法中的操作.
  • 运行状态线程不是一直占用CPU的,而是根据CPU的调度策略有关.CPU时间片用完后,就会转为就绪状态.
  • 操作系统的调度策略,会考虑线程的优先级.高优先级的线程获得CPU调度几率要大.
  • 多于处理器内核数目的线程数,并不能提供执行效率.



阻塞 Blocked

在某些情况下,一个正在运行的线程会让出正在使用的CPU资源,进入阻塞状态.

  • 某些共享资源(打印机或文件资源)被占用.
  • 等待I/O操作.
  • 调用了wait、sleep或者 suspend 等方法.
  • 尝试获得锁,而该锁正在被其他线程使用.

为了提供CPU的利,当一个线程被阻塞时,另一个线程就获得了运行的机会.



终止 Terminated

线程到达终止状态可能有几种原因:

  • 线程的方法

    run()

    执行结束.
  • 线程通过某些方法(如

    Destory()

    ) 被提前终止.


  • run()

    方法执行中发生了未捕获的异常.



线程的优先级

在 JAVA 语言中,每个线程都有一个优先级,不同线程可以被赋予不同的优先级.

通过

getPriority()

方法获取线程优先级,通过

setPriority()

方法设置线程优先级.

线程优先级共分为10个级别,最低为1,最高为10,默认优先级为5.



守护线程

前面提到的都是用户线程,另外还有一个是守护线程.两者没有什么太大不同,守护线程的唯一作用是为用户线程提供服务.

通过

setDaemon()

方法,将线程设置为守护线程.



版权声明:本文为qq_44863814原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。