进程: 一个正在执行程序的实例, 包括程序计数器, 寄存器以及变量的当前值. 在操作系统中, 每一个进程都有其地址空间和控制线程.
地址空间: 要保证多个应用程序同时处于内存中并且不互相影响, 则需要解决两个问题: 保护和重定位. 目前的办法是创造一个新的内存抽象: 地址空间. 就像进程的概念创造了一类抽象的 CPU 以运行程序一样, 地址空间为程序创造了一种抽象的内存. 地址空间是一个进程可用于寻址内存的一套地址集合. 每个进程都有一个自己的地址空间, 并且这个地址空间独立于其他进程的地址空间.
线程: 存在同一个地址空间存在多个控制线程的情况. 线程是操作系统能够进行运算调度的最小单位, 是进程中的实际运作单位. 一个线程指的是进程中一个单一顺序的控制流.
在 Unix System V 及 SunOS 中也被称为轻量进程 (lightweight processes), 但轻量进程更多指内核线程(kernel thread), 而把用户线程(user thread) 称为线程.
同一进程中的多条线程将共享该进程中的全部系统资源, 如虚拟地址空间, 文件描述符和信号处理等等. 但同一进程中的多个线程有各自的调用栈(call stack), 自己的寄存器环境(register context), 自己的线程本地存储(thread-local storage).
多线程的好处 在多核或多 CPU, 或支持 Hyper-threading 的 CPU 上使用多线程程序设计的好处是显而易见, 即提高了程序的执行吞吐率. 在单 CPU 单核的计算机上, 使用多线程技术, 也可以把进程中负责 I/O 处理, 人机交互而常被阻塞的部分与密集计算的部分分开来执行, 编写专门的 workhorse 线程执行密集计算, 从而提高了程序的执行效率.
runnable: 封装了代码执行序列的线程对象.
创建 Runnable: 实现 Runnable 接口的匿名类 / lambda 表达式.
创建线程: 将 Rannable 对象作为 Thread 类的构造函数参数. 直接继承 Thread 类, 并重写 run().
- // 通过 Runnable 传递到 Thread 类中
- Runnable r = new Runnable() {
- @Override
- public void run() {
- // work
- }
- }
- Thread t = new Thread(r);
- // 直接继承 Thread 类
- Class MyThread extends Thread {
- @Override
- public void run() {
- // work
- }
- }
- MyThread t = new MyThread();
线程的 5 个特征: 线程名称, 存活标识, 执行状态, 优先级以及是否为守护进程.
线程的执行状态: NEW,RUNNABLE,BLOCKED,WAITTING,TIME_WAITTING,TERMINATED.
一些基本操作
线程的中断: interrupt(),interrupted(),isInterrupted().
等待线程: join()方法, 当一个线程启动另一个线程时, 被启动的线程非常耗时, 主线程调用 join()方法, 主线程会等待该线程完成工作再处理其结果.
- class ThreadJoining extends Thread {
- @Override
- public void run() {
- for (int i = 0; i < 2; i++) {
- try {
- Thread.sleep(500);
- System.out.println("C Current Thread:"
- + Thread.currentThread().getName());
- } catch (Exception ex) {
- System.out.println("Exception has" +
- "been caught" + ex);
- }
- System.out.println(i);
- }
- }
- }
- public class GFG {
- public static void main(String[] args) {
- // creating two threads
- ThreadJoining t1 = new ThreadJoining();
- ThreadJoining t2 = new ThreadJoining();
- ThreadJoining t3 = new ThreadJoining();
- // thread t1 starts
- t1.start();
- // starts second thread after when
- // first thread t1 is died.
- try {
- System.out.println("A Current Thread:"
- + Thread.currentThread().getName());
- t1.join();
- } catch (Exception ex) {
- System.out.println("Exception has" +
- "been caught" + ex);
- }
- // t2 starts
- t2.start();
- // starts t3 after when thread t2 is died.
- try {
- System.out.println("B Current Thread:"
- + Thread.currentThread().getName());
- t2.join();
- } catch (Exception ex) {
- System.out.println("Exception has been" +
- "caught" + ex);
- }
- t3.start();
- }
- }
- result:
- A Current Thread: main
- C Current Thread: Thread-0
- 0
- C Current Thread: Thread-0
- 1
- B Current Thread: main
- C Current Thread: Thread-1
- 0
- C Current Thread: Thread-1
- 1
- C Current Thread: Thread-2
- 0
- C Current Thread: Thread-2
- 1
在这个例子里是主线程等待被启动线程完成工作 (死亡) 才会处理接下来的工作.
线程睡眠: Thread.sleep() 暂时性停止执行.
来源: https://juejin.im/post/5bc4650c5188255c713cafac