【Java进阶】带你了解多线程

134 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


多线程

多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。简单地说,就是一个同一个跑道上在跑步的人,这些人就可以当作是线程,而跑道则可以当作是时间段。生活中,我们用的手机、电脑能够同时进行聊天、看视频、听音乐等,就是多线程的功劳。

1. 线程和进程

所谓进程,即一个内存中运行的应用程序。每个进程都有自己独立的内存空间,一个进程可以有多个线程(1,n)。

所谓线程,即进程中的一个执行任务(控制单元)。每个进程可以运行多个线程,多个线程可以共享信息。

2. 并发和并行

并发,即同一时间段执行多个任务。

并行,即同一时间点执行多个任务。

3. 线程的创建和启动

3.1 继承 Thread 类
  • 自定义类继承Thread类

  • 重写run()方法

  • 创建自定义类对象

  • 调用start()方法

image.png

3.2 实现Runnable接口
  • 自定义类实现Runnable接口
  • 实现run()方法
  • 创建自定义类对象
  • 创建Thread对象并将自定义类对象作为对象传入
  • 调用start()方法

image.png

3.3 两种方式比较

(1)从类和接口的特性上分析

  • Java中类只能单继承,继承Thread类后将不能继承其它直接父类
  • Java中类可以多实现接口,实现Runnable接口后可以继承其它类,也可以实现其它接口

(2)从操作上分析

  • 继承方式和获取线程名字都比较简单super.getName()
  • 实现方式和获取线程名字都比较麻烦Thread.currentThread().getName()

(3)从多线程共享同一资源上分析

  • 继承方式多个线程不能共享同一个资源
  • 实现方式多个线程能够共享同一个资源

4. 线程执行的随机性

一个线程启动之后将成为一个独立的个体,等待CPU的调度分配资源,不会因为启动它的外部线程结束而结束。

image.png

5. 线程的生命周期

状态名称说明
初始状态(NEW)表示线程被创建了,但没有调用start()方法,由Java虚拟机为其分配内存并初始化成员变量值
运行状态(RUNNABLE)可以细分为就绪状态(READY)和运行状态(RUNNING)两种状态。 就绪状态:当线程调用start()方法后,线程就处于就绪状态,进入了线程队列排队,但此时线程并未开始执行,仅仅是获得了运行的资格,而运行的时期取决于CPU调度器的调度。 运行状态:表示线程对象被CPU调度器调度了,可以执行线程体。
阻塞状态(BLOCKED)表示正在运行的线程遇到某种特殊情况,比如同步、等待I/O操作完成等。进入阻塞状态的线程让出CPU资源,并暂停自己的执行。
等待状态(WAITING)进入该状态表示当前线程需要等待其它线程做出一些特定动作(比如调用notify、notifyAll方法),才能够重新进入RUNNABLE状态
超时等待状态(TIME_WAITING)与等待状态不同,处于该状态的线程达到设定的时间后可以自行返回
终止状态(TERMINATED)表示当前线程已经执行完毕

image.png

6. 常用方法

方法说明
join()使线程进入阻塞状态,只有线程执行完才往下执行
sleep(long millis)使正在执行的线程进行暂停一段时间(单位:毫秒),进入阻塞状态(常用于模拟网络延迟)
getPriority()获取线程的优先级(1~10),默认为5(优先级高低只与线程获得执行机会的次数多少有关)
setPriority(int n)更改线程的优先级
setDaemon(boolean on)将线程标记为守护线程或用户线程(必须在start()调⽤前,否则抛IllegalThreadStateException异常)

7. 线程同步

7.1 解决方法

(1)同步代码块

synchronized(同步锁){

}

(2)同步方法

  • 使用synchronized修饰的方法(将需要同步的代码抽取为一个方法,并使用synchronized修饰)
  • 同步锁是谁?
    • 对于非静态方法,同步锁为this
    • 对于静态方法,同步锁为类名.class

(3)同步锁

  • 同步锁又称为同步监听对象/同步监听器/互斥锁\
  • Java程序允许使用任何对象作为同步监听对象,一般选择当前并发访问的共同资源作为同步监听对象(this、类名.class)
  • 在任何时候,最多允许一个线程拥有同步锁,获得同步锁的线程先执行,其它线程在代码块外等候