进程, 线程, 协程的区别

进程 Process

进程提供了执行一个程序所需要的所有资源, 一个进程的资源包括虚拟的地址空间, 可执行的代码区, 可用的系统接口, 本地存储, 系统保障的安全上下文(security context), 唯一的进程ID, 环境变量, 优先级, 以及至少一个工作线程. 每个进程都是从一个主线程启动, 然后在运行中创建更多的线程.

  • 进程是操作系统资源分配的最小单位
  • 同一时刻在系统中执行的进程数不会超过核心数
  • 进程之间是隔离的
  • 进程之间有层级关系, 由内核直接创建的进程没有父进程, 除此以外进程都是由其它进程创建的
  • 父进程退出并不会终止子进程

线程 Thread

线程是运行于进程中的一个可以调度运行的实例, 在一个进程中的所有线程, 共用这个进程的虚拟地址空间和其它系统资源(前面进程中提到的进程资源), 除此以外, 还有自己唯一的线程ID, 线程的上下文变量(用于系统调度), 这些上下文变量包含线程的寄存器, 内核堆栈, 环境变量等. 线程也有自己的安全上下文.

进程和线程的区别

  • 进程是操作系统资源分配的基本单位,线程是独立运行和独立调度的基本单位
  • 进程使用单独的地址空间, 而线程(同一个进程下)使用共享地址空间
  • 线程创建和调度的开销比进程小
  • 线程因为共享地址空间, 同一进程的线程间通信很方便

协程 Coroutine

协程是一个特殊的函数, 这个函数可以在运行中被"挂起:, 可以重新在挂起处继续运行. 协程是比线程更加轻量级的一种并发模式.

一个线程中的多个协程的运行是串行的, 一个线程内可以运行多个函数, 但这些函数都是串行运行的, 当一个协程运行时, 其他协程就处于挂起状态. 单独使用协程无法利用CPU的多核资源.

协程和线程的区别

线程是由操作系统调度的, 是操作系统层级的并发, 而协程是完全由程序所控制的, 即在用户态执行, 一个线程可以同时运行多个协程, 运行的开销更小. 线程可以利用CPU的多核资源, 协程不可以, 需要与线程或进程配合.

讲讲ThreadLocal 是什么

ThreadLocal 提供线程的局部变量, 每一个访问该变量的线程在 ThreadLocal 内部都有一个独立的初始化的变量, ThreadLocal 实例变量通常采用private static 在类中修饰. 每个线程都会持有自己的ThreadLocal 实例, 当一个线程结束时,它所持有的所有 ThreadLocal 实例会被回收. ThreadLocal 解决了多线程之间数据隔离问题.

ThreadLocal 使用场景

ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也就是变量在线程间隔离,而在同一线程共享的场景。例如管理Connection,我们希望每个线程只使用一个Connection实例,这个时候用ThreadLocal就很合适.

使用方法为

ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
threadLocal.set(1);
threadLocal.get();
threadLocal.remove();

示例代码

public class Demo {
private static final ThreadLocal<Object> threadLocal = new ThreadLocal<>(); public static void main(String[] args) {
threadLocal.set(new Object());
someMethod();
} static void someMethod() {
// 获取在threadLocal中存储的对象
threadLocal.get();
// 处理
dosomthing();
// 清除
threadLocal.remove();
}
}

ThreadLocal 作为变量的线程隔离是如何实现的?

ThreadLocal 实现原理是什么?

在了解了如何使用之后,看下 ThreadLocal 是如何实现的

ThreadLocal.get()

看get方法的源码,可以看到方法中获取当前线程,并通过当前线程得到一个 ThreadLocalMap,然后通过 this(当前ThreadLocal对象)作为key,从Map中获取Entry

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

For example, the class generates unique identifiers local to each thread. A thread's id is assigned the first time it invokes ThreadId.get() and remains unchanged on subsequent calls.

通过 private static final 类型的变量实现. 在Thread实例中有一个 ThreadLocalMap类型的成员变量, 用来存多个ThreadLocal及其对应的值. 这时候可以new一个或多个ThreadLocal, 这个ThreadLocal实例会自动存入Thread的ThreadLocalMap里

private static final ThreadLocal threadSession = new ThreadLocal();

再往里面set值

threadSession.set(s);

做set操作时, 在ThreadLocalMap里以for循环的方式来取Entry, 判断key是否是这个ThreadLocal, 是的话才set.

用完后可以从ThreadLocalMap里面把这个ThreadLocal实例为key的值remove掉

threadSession.remove();

说说 InheritableThreadLocal 的实现原理?

InheritableThreadLocal 如何弥补 ThreadLocal 不支持继承的特性?

This class extends ThreadLocal to provide inheritance of values from parent thread to child thread: when a child thread is created, the child receives initial values for all inheritable thread-local variables for which the parent has values. Normally the child's values will be identical to the parent's; however, the child's value can be made an arbitrary function of the parent's by overriding the childValue method in this class.

Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.

由于ThreadLocal设计之初就是为了绑定当前线程, 如果希望当前线程的ThreadLocal能够被子线程使用, 实现方式就会相当困难, 需要用户自己在代码中传递. InheritableThreadLocal主要用于子线程创建时, 需要自动继承父线程的ThreadLocal变量, 方便必要信息的进一步传递.

Thread类中包含 threadLocals 和 inheritableThreadLocals 两个变量, 其中 inheritableThreadLocals 即主要存储可自动向子线程中传递的ThreadLocal.ThreadLocalMap

采用默认方式产生子线程时, inheritThreadLocals=true;若此时父线程inheritableThreadLocals不为空, 则将父线程inheritableThreadLocals传递至子线程

ThreadLocalRandom 如何利用 ThreadLocal 的原理来解决 Random 的局限性?

Thread里有一个 threadLocalRandomSeed 变量, 就是专门用来给ThreadLocalRandom作为seed使用的, 里面还有一个threadLocalRandomProbe变量, 用户判断threadLocalRandomSeed是否已经初始化, 如果probe不为0, 则seed已经初始化.

SpringMVC 中如何使用 ThreadLocal 实现 request scope 作用域 Bean?

对应的代码, 可以看到 RequestAttributes 是用 ThreadLocal 类型存储的

public abstract class RequestContextHolder {
private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context"); @Nullable
public static RequestAttributes getRequestAttributes() {
RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
if(attributes == null) {
attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
} return attributes;
}

Java多线程专题3: Thread和ThreadLocal的更多相关文章

  1. Java多线程专题5: JUC, 锁

    合集目录 Java多线程专题5: JUC, 锁 什么是可重入锁.公平锁.非公平锁.独占锁.共享锁 可重入锁 ReentrantLock A ReentrantLock is owned by the ...

  2. Java多线程专题1: 并发与并行的基础概念

    合集目录 Java多线程专题1: 并发与并行的基础概念 什么是多线程并发和并行? 并发: Concurrency 特指单核可以处理多任务, 这种机制主要实现于操作系统层面, 用于充分利用单CPU的性能 ...

  3. Java多线程专题2: JMM(Java内存模型)

    合集目录 Java多线程专题2: JMM(Java内存模型) Java中Synchronized关键字的内存语义是什么? If two or more threads share an object, ...

  4. Java多线程专题4: 锁的实现基础 AQS

    合集目录 Java多线程专题4: 锁的实现基础 AQS 对 AQS(AbstractQueuedSynchronizer)的理解 Provides a framework for implementi ...

  5. Java多线程专题6: Queue和List

    合集目录 Java多线程专题6: Queue和List CopyOnWriteArrayList 如何通过写时拷贝实现并发安全的 List? CopyOnWrite(COW), 是计算机程序设计领域中 ...

  6. Java多线程4:Thread中的静态方法

    一.Thread类中的静态方法 Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可 ...

  7. java 多线程2:Thread的实例方法

    Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1 ...

  8. java 多线程3:Thread类中的静态方法

    Thread类中的静态方法 Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程".为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程 ...

  9. Java多线程系列八——volatile和ThreadLocal

    参考资料: http://ifeve.com/java-memory-model-4/ http://www.infoq.com/cn/articles/java-memory-model-1 htt ...

随机推荐

  1. 【LeetCode】62. Unique Paths 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/unique-pa ...

  2. C. Tourist's Notes

    C. Tourist's Notes time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  3. Codeforces Round #358 (Div. 2) C. Alyona and the Tree

    C. Alyona and the Tree time limit per test 1 second memory limit per test 256 megabytes input standa ...

  4. isEmpty 和 isBlank 的区别

    一般使用Apache commons-lang3 工具包: commons-lang3 是专业的工具包,功能非常齐全.强大. 1.isEmpty 判断字符串是否为空字符串,只要有一个任意字符(包括空白 ...

  5. Wiener Filtering

    目录 基本 滤波的推导 特别的情况 特别的例子 Signals, Systems and Inference, Chapter 11: Wiener Filtering (mit.edu) 基本 在图 ...

  6. CS5266代替AG9311|Type C转HDMI带PD3.0转换芯片|AG9311替代方案

    ALGOLTEK AG9311是一款带PD3.0 Type C转HDMI的转换芯片,它主要用于usb Type-c拓展坞以及多功能usb Type-c转换器等产品设计当中,台湾瑞奇达新推出的CS526 ...

  7. Spring企业级程序设计作业目录(作业笔记)

    Spring企业级程序设计 • [目录] 第1章 Spring之旅  >>> 1.1.6 使用Eclipse搭建的Spring开发环境,使用set注入方式为Bean对象注入属性值并打 ...

  8. 使用 jQuery 操作页面元素的方法,实现浏览大图片的效果,在页面上插入一幅小图片,当鼠标悬停到小图片上时,在小图片的右侧出现与之相对应的大图片

    查看本章节 查看作业目录 需求说明: 使用 jQuery 操作页面元素的方法,实现浏览大图片的效果,在页面上插入一幅小图片,当鼠标悬停到小图片上时,在小图片的右侧出现与之相对应的大图片 实现思路: 在 ...

  9. Nginx 加载conf.d (内文件***.conf)

    include /usr/local/nginx/conf/conf.d/*.conf;

  10. Centos7 mysqldump定时任务,对mysql定时备份数据

    vi mysqldump_bak.sh #!/bin/bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/ ...