线程基础
- Java
- 2021-04-23
- 513热度
- 0评论
导航
1 初识线程
1.1 什么是线程
线程是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务,共享内存资源。
1.2 线程与进程的区别
- 是否拥有资源:进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
- 系统开销:创建、撤销及切换操作,线程的开销远小于进程。
- 通信方式:线程间通信可以直接访问进程中的同一内存空间,进程间通信需要借助 IPC。
1.3 为什么需要线程
多线程,使得一个进程可以同时做好几件事。当进程中的某些线程阻塞时,另一些线程依旧可以执行,不需要把整个进程挂起。
另外,由于线程的开销比进程小很多(被称为“轻量级进程”),常使用多线程做并发编程(而不是多进程)。
实际运用举例:
- 一个浏览器可以同时下载几幅图片;
- 一个 Web 服务器可以同时服务并发的请求;
- GUI 程序用一个独立的线程从宿主操作环境收集用户界面事件。
1.4 Java 中怎样创建一个线程
主要有两个基本方式:
- 继承 Thread 类
- 实现 Runnable 接口
第一种方式已经不推荐了,建议直接用第二种方式。为什么?因为实现 Runnable 接口的方式,可以将“并发任务”与“运行机制”解耦,更加灵活。可以选择为每个任务创建一个单独的线程,或是直接交给线程池。
以下是一个 demo:
public class RunnableTest { public static void main(String[] args) { Runnable r = () -> { for (int i = 0; i < 50; i++) { System.out.printf("%s %s\n", Thread.currentThread().getName(), i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }; Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); } }
2 扩展知识
2.1 线程状态
线程有 6 种状态:
- New(新建):线程刚创建,但还未运行(未调用 start 方法);
- Runnable(可运行):调用 start 方法之后。一个可运行的线程可能正在运行也可能没有运行;
- Blocked(阻塞):当一个线程试图获取一个内部的对象锁,而这个锁目前被其他线程占有,该线程就会被阻塞;
- Waiting(等待):当线程等待另一个线程通知调度器出现一个条件时,这个线程会进入等待状态。调用 Object.wait 方法或 Thread.join 方法,或者是等待 java.util.concurrent 库中的 Lock 或 Condition 时,就会出现这种情况;
- Timed waiting(计时等待):有几个方法有超时参数,调用这些方法会让线程进入计时等待状态。这一状态将一直保持到超时或接收到适当的通知。带有超时参数的方法有 Thread.sleep 和计时版的 Object.wait、Thread.join、Lock.tryLock 以及 Condition.wait;
- Terminated(终止):(1)run 方法正常退出,线程自然终止;(2)未捕获的异常终止了 run 方法,使线程意外终止。
当线程处阻塞或等待状态时,它暂时是不活动的。它不运行任何代码,而且消耗最少的资源。
状态转换图如下:
2.2 守护线程
可以调用 t.setDaemon(true),将一个线程转换为守护线程。
守护线程的唯一用途是为其他线程提供服务。当只剩下守护线程时,虚拟机就会退出。
举例:垃圾回收线程。
ref:
- 《Java 核心技术(卷1)》
- 进程 线程 协程 管程 纤程 概念对比理解