前言
当我们设计微服务时,微服务的用户大多数情况下是同时发送很多请求给我们。 那么就要求在我们微服务的内部需要能够有多个线程(Thread) 来处理这些请求。(我们的微服务只是对外开放一个port 但是为什么能同时接受很多request? 这个问题我会单独写一篇.) 简单来说,我们的server的主进程作为一个任务的发布者,使用线程来进行分发任务。多个任务同时进行那么就会用到Concurrency。
正文
一些概念:
- 进程:一段运行的程序,不和其他程序分享memory等。一个进程能包含多个线程。(StackoverFlow)
- 线程:一段运行的程序, 和其他程序分享memory等。
- Runnable 接口: 实现它的类能被用来创建Thread instance. Github Code
- Thread 类: 继承它的类能直接创建Thread instace. Github Code
- Runnable 和 Thread 的区别: java是单继承的,当我们的应用复杂的时候建议使用 实现runnable的接口。Thread类提供了很多简单的实现,所以当我们的应用不是很复杂的时候我们可以使用它.
- Interrupt: 被用来打断thread的活动,打断的方式大致有: 当从外部线程打断时,如果被打断线程处于 wait, join, sleep, 那么被打断thread立马throw interruptation exception; 如果被打断线程处于 正常的工作状态的时候,那么该线程的interrupted 状态会被设为 true。
- Join: ThreadObj.join() 调用join的线程会等待 ThreadObj 完成 之后才继续运行。如果TheadObj 在join被调用之前已经完成了,那么ThreadObj.join 会立马结束. Github Code
- Thread Interference: 线程干扰 - 当多个线程同时对一个对象进行一系列的操作时,这个对象的最终状态可能是错误的. 原理是因为即使是很简单的java操作,它也是由多个“原子”级别的操作组成的,多线程时在不同线程之间java不能保证它们的运行顺序. 8-11 在 Github 中有更详细的解释
- Memory Consistency Error: 更多的是 architecture-specific, 他的大概意思就是不是所有的线程都能够访问的到shared memory里面的最新的信息,有可能这个shared memory里面的数据还没来得及被更新。使用happens-before来避免, 它保证了对内存的操作能被其他的操作所看到。
- Synchronized Method 和 Synchronized statments: 用它来避免thread interference 并且建立happens before 关系
- Happens before 关系: 假设 Thread A 中的事件 X 和 在Thread B中的事件Y 建立了Happens Before 关系,那么就意味着 A和 B这两个线程对内存里面数据的一致性也遵循 X 然后 Y这个顺序. 比如 X 是对数据 i 进行加一,那么 Y 读取i的时候得到的数据就是在X发生之后 i 的结果。
- Dead Lock: 死锁 多个线程相互争抢资源,各自为营互不相让。12-14 在Github 中有更纤细的解释。
- Starvation: 饿死,造成的原因是 一个类提供多个synchronized 方法,但是某个方法会运行非常长的时间,然后有的线程对他的访问频率很高的话,这就造成其他线程访问其他的syncronized 方法被阻止.
- Livelock: 活锁也是线程之间的堵塞的一种形式,但是是动态堵塞。举个栗子,我们有一个queue,然后我们的系统的poller 对其取 数据然后处理如果发生错误就把数据放回queue里面等待重试,如果对于某个数据它一直错误我们就一直处理这个不能被处理的数据,这就是活锁。
如有问题欢迎指出!感谢