
获得徽章 0
# 用饭店来形象比喻线程池的工作原理
线程池通过维护一定数量的线程避免频繁创建和销毁带来的资源损耗。其工作原理可类比为饭店,任务是客人,线程是厨师,队列则用来排队。
当厨师(线程)不足时,新任务会等待;若资源耗尽,会采取拒绝策略,如放弃任务或上报错误。当无任务时,部分线程会被释放或保持待命状态。
## 一、线程池解决的问题?
使用线程池主要解决在程序中频繁创建和销毁线程导致的资源浪费,线程池可以维护一定量的线程来执行所需要的任务,维护的线程也可以重复使用。
## 二、用形象的饭店来解释工作原理
- 线程池就相当于一家饭店,
- 任务就相当于来饭店吃饭的客人
- 线程就相当于饭店的厨师
- 队列就相当于饭店外面提供排队的板凳
## 三、工作原理 如图:
## 四、类似于餐厅的工作原理
客人前来点餐 餐厅分配正式厨师做饭:
如果正式厨师不够用,就去排队;
如果外面的排队小板凳用完,餐厅会招聘临时厨师做饭;
如果临时厨师也用完,也没有办法排队就使用拒绝策略 放弃这个客户 让客户自己做饭吃;
上报错误;
丢弃让最先排队的客户,为当前客户做饭;
上报错误(没有原因);
如果所有客户都有饭吃了,那么临时厨师和正式厨师就等待新客户;
临时厨师等一定时间还没有客户就被辞退;
正式厨师将一直等待新客户。
转自:
blog.csdn.net
线程池通过维护一定数量的线程避免频繁创建和销毁带来的资源损耗。其工作原理可类比为饭店,任务是客人,线程是厨师,队列则用来排队。
当厨师(线程)不足时,新任务会等待;若资源耗尽,会采取拒绝策略,如放弃任务或上报错误。当无任务时,部分线程会被释放或保持待命状态。
## 一、线程池解决的问题?
使用线程池主要解决在程序中频繁创建和销毁线程导致的资源浪费,线程池可以维护一定量的线程来执行所需要的任务,维护的线程也可以重复使用。
## 二、用形象的饭店来解释工作原理
- 线程池就相当于一家饭店,
- 任务就相当于来饭店吃饭的客人
- 线程就相当于饭店的厨师
- 队列就相当于饭店外面提供排队的板凳
## 三、工作原理 如图:
## 四、类似于餐厅的工作原理
客人前来点餐 餐厅分配正式厨师做饭:
如果正式厨师不够用,就去排队;
如果外面的排队小板凳用完,餐厅会招聘临时厨师做饭;
如果临时厨师也用完,也没有办法排队就使用拒绝策略 放弃这个客户 让客户自己做饭吃;
上报错误;
丢弃让最先排队的客户,为当前客户做饭;
上报错误(没有原因);
如果所有客户都有饭吃了,那么临时厨师和正式厨师就等待新客户;
临时厨师等一定时间还没有客户就被辞退;
正式厨师将一直等待新客户。
转自:
展开
评论
1
一致性哈希速记
普通哈希:var x = hash(dataKey) % N
一致性哈希:将数据的key的hashcode与存放数据的节点(如缓存节点)的IP(或服务器名)的hashcode都分布到同一个环形数值空间,比如 0~2^32-1。然后,把数据的 hashcode 沿着顺时针方向找第一个存放数据的节点的hashcode,找到的那个就是要存放的节点。
```
var dataValue = hash(dataKey) % N
var nodeValue = hash(nodeIP) % N
```
将dataValue沿数值空间顺时针寻找第一个nodeValue,找到的那个对应的node就是要存放数据的节点。
一致性哈希数据不均匀的问题:
通过增加虚拟节点的思路,为每个node设计多个虚拟节点(比如100个),虚拟节点可以在物理节点的IP的基础之上加上数字后缀。然后把虚拟节点hash分布到hash环。然后我们先按照上面的一致性哈希思路计算出需要存放的虚拟节点,然后再根据虚拟节点和物理节点的对应关系,找到具体的物理节点。
普通哈希:var x = hash(dataKey) % N
一致性哈希:将数据的key的hashcode与存放数据的节点(如缓存节点)的IP(或服务器名)的hashcode都分布到同一个环形数值空间,比如 0~2^32-1。然后,把数据的 hashcode 沿着顺时针方向找第一个存放数据的节点的hashcode,找到的那个就是要存放的节点。
```
var dataValue = hash(dataKey) % N
var nodeValue = hash(nodeIP) % N
```
将dataValue沿数值空间顺时针寻找第一个nodeValue,找到的那个对应的node就是要存放数据的节点。
一致性哈希数据不均匀的问题:
通过增加虚拟节点的思路,为每个node设计多个虚拟节点(比如100个),虚拟节点可以在物理节点的IP的基础之上加上数字后缀。然后把虚拟节点hash分布到hash环。然后我们先按照上面的一致性哈希思路计算出需要存放的虚拟节点,然后再根据虚拟节点和物理节点的对应关系,找到具体的物理节点。
展开
评论
点赞
RBAC 模型速记:
Core concept: user,role,permission,operation,resource
- user has many roles, assign role to user; one role can be assigned to many users.
- user has many permissions, assign permission to user; one permission can be assigned to many users.
- role has many permissions, a role is a package of permissions.
- operation is like add, update, delete, import, download, visible, invisible, etc.
- resource is like menu, button, or other screen elements.
- permission has many resources and operations; one resource can be used by many permissions; one operation can be used by many permissions.
Core concept: user,role,permission,operation,resource
- user has many roles, assign role to user; one role can be assigned to many users.
- user has many permissions, assign permission to user; one permission can be assigned to many users.
- role has many permissions, a role is a package of permissions.
- operation is like add, update, delete, import, download, visible, invisible, etc.
- resource is like menu, button, or other screen elements.
- permission has many resources and operations; one resource can be used by many permissions; one operation can be used by many permissions.
展开
评论
1
赞了这篇文章
应用了像 JWT 这种无状态的 Token 后,业务系统是可以不用与像 IAM 这样的认证中心进行通讯,否则的话,每一次请求就远程通讯一次认证中心,成本很高。但这样只是解决了“我是谁”的认证问题,但如果要获取用户的权限信息,是否又要跟认证中心通讯呢?因为用户的权限信息也是保存在认证中心中。
9
1
漏桶(Leaky bucket)与令牌桶(Token bucket)算法有什么区别。
令牌桶,初始令牌个数是0,最大容量是100,当1万个请求到来时(初始令牌个数是0时),也只能一秒处理一个请求个,因为令牌是每秒产生一个。
漏桶,初始流量是0,最大流量是100,当1万个请求到来时,可以迅速的,最多的,能同时处理100个。
=============================================
令牌桶,初始令牌个数是100,最大容量是100,当1万个请求到来时(初始令牌个数是0时),可以迅速的,最多的,同时处理100个请求,从第101个请求开始,也只能等新令牌的产生,而令牌是每秒产生一个。
漏桶,初始流量是0,最大流量是100,当1万个请求到来时,可以迅速的,最多的,能同时处理100个。
令牌桶,初始令牌个数是0,最大容量是100,当1万个请求到来时(初始令牌个数是0时),也只能一秒处理一个请求个,因为令牌是每秒产生一个。
漏桶,初始流量是0,最大流量是100,当1万个请求到来时,可以迅速的,最多的,能同时处理100个。
=============================================
令牌桶,初始令牌个数是100,最大容量是100,当1万个请求到来时(初始令牌个数是0时),可以迅速的,最多的,同时处理100个请求,从第101个请求开始,也只能等新令牌的产生,而令牌是每秒产生一个。
漏桶,初始流量是0,最大流量是100,当1万个请求到来时,可以迅速的,最多的,能同时处理100个。
展开
评论
2
原来 uuid v7 实现如此简单:
```java
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.UUID;
public class UUIDv7 {
private static final SecureRandom RANDOM = new SecureRandom();
public static UUID randomUUID() {
byte[] value = randomBytes();
ByteBuffer buf = ByteBuffer.wrap(value);
long high = buf.getLong();
long low = buf.getLong();
return new UUID(high, low);
}
private static byte[] randomBytes() {
// random bytes
byte[] value = new byte[16];
RANDOM.nextBytes(value);
// current timestamp in ms
ByteBuffer timestamp = ByteBuffer.allocate(Long.BYTES);
timestamp.putLong(System.currentTimeMillis());
// timestamp
System.arraycopy(timestamp.array(), 2, value, 0, 6);
// version and variant
value[6] = (byte) ((value[6] & 0x0F) | 0x70);
value[8] = (byte) ((value[8] & 0x3F) | 0x80);
return value;
}
}
```
```java
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.UUID;
public class UUIDv7 {
private static final SecureRandom RANDOM = new SecureRandom();
public static UUID randomUUID() {
byte[] value = randomBytes();
ByteBuffer buf = ByteBuffer.wrap(value);
long high = buf.getLong();
long low = buf.getLong();
return new UUID(high, low);
}
private static byte[] randomBytes() {
// random bytes
byte[] value = new byte[16];
RANDOM.nextBytes(value);
// current timestamp in ms
ByteBuffer timestamp = ByteBuffer.allocate(Long.BYTES);
timestamp.putLong(System.currentTimeMillis());
// timestamp
System.arraycopy(timestamp.array(), 2, value, 0, 6);
// version and variant
value[6] = (byte) ((value[6] & 0x0F) | 0x70);
value[8] = (byte) ((value[8] & 0x3F) | 0x80);
return value;
}
}
```
展开
1
1