领导力的学习

谦虚的提问:
1,思想上游启发。你提的问题能够启发对方思考,让对方

1 思想上有启发。你提的问题能够启发对方思考,让对方想得更多,想得更深
2.情感上有激励。你提的问题能够给对方提供正能量。
3.关系上有促进。你提的问题能够促进你和对方的关系
4.行动上有推动。你提的问题,能够推动对方积极行动起来。

1鼓励,2提示 拆解 3 提示,借力,群力

正确的领导力故事主要有四种:
分别是
我是谁的故事;
我们是谁的故事;
我们向何处去的故事;
还有我们为什么要变革的故事。

离听众距离越近的股市越能打动情感,越能引起情感的共鸣。

有三种谦虚。第一种谦虚是面对身份更高的人的时候,比如平民面对贵族,下级面对上级,我们往往会谦虚。第二种谦虚是面对成就更大的人的谦虚,比如你是一个刚刚创业的人,你面对比尔盖茨。

第三种谦虚是因为你以来他人而产生的谦虚,你知道这件事情自己一个人干不成,你要依靠对方才能干成功。是有意你谦虚。

提问容易建立关系。

尽量不要唱反调

1不要只想着自己埋头做事情,要借助上级的资源;2让领导多参与自己的工作(宜家效应),怎么做到呢?多汇报,多请示 ; 3 帮助上级解决难题,而不是给上级出难题

我不知道的第三种情况。你已经有了答案,但是你说“”我不知道“”,因为你先鼓励下属,鼓励其他人先说他们的答案,看能不能发现更好的答案。

啊呀。这个问题太难了。我一时也没有想好。要不咋们俩现在讨论一下,看能不能讨论一个解决方案来?

宜家效应

如果你想要其他人更加喜欢一个想法,更加积极主动地去实现一个想法,最好的方式不是告诉他这个想法,而是你不动声色地提供一些素材,让他自己把这个想法组装出来,让他认为是他自己的想法。

一个维度是下属是有独立的,批判性的思考,还是依赖上级替他们思考?另一个维度是下属积极主动地参与工作,还是消极被动地参与。

凯利把有独立思考,又积极参与的员工称为明星。

商业竞争会倒逼包容性领导产生。目前包容性的环境不好,我们的教育强调唯一正确的答案,某种意义上就是扼杀了批判性思维。我们儒家文化是集体主义文化,不是大一统意见的人会被带上 :“异类”,自以为是,不服从大局,不听话,特立独行,等帽子。尤其是在机关事业单位里面。唱反调的人面临的风险真的很大。但是,在残酷的商业竞争环境下,企业面临的不确定性越来越大,这可能会倒逼产生包容性的领导。因为领导不是全能智者,他不知道的东西也很多,充分听取和包容各种不同声音也许会更好地促进企业在竞争中生存。

追随力的三个要点:第一,委婉地唱反调。第二,积极地唱反调。第三,向上建立关系。追随力就是,动员领导解决难题。在决策时候,我如果有不同的意见,觉得老板有不妥就会踢出来。说明理由,并且指明方向,然后共同讨论,老板都接受我的意见。但是我不会再众股东面前提出异议,而是单独以商讨,或者进言方式提出。你看,不要当着大家说,而是私下里面悄悄说,你给老板留了面子,老板就更加可能接受你的意见。

为难式唱反调。

在这里插入图片描述
面对一个集体难题,你挺身而出,说 我来。你和上级和平级说 ,让我来,对下属说,跟我来。
在这里插入图片描述
面对一个挑战性难题,即使你已经有了答案,你也说“”“我不知道”,动员他人自己去发现答案。

在这里插入图片描述
当下属来向你请示时,你问,你觉得呢?这个问题启发思想,激励情感,推进行动。

写书(技术书籍)的精华:我们采取一种基于问题求解的方式:这是一个问题,我该怎么解决? 如何对候选方案进行权衡取舍?我们从基础知识开始,循序渐进,每一章都建立在前一章之上,同时提供必要的实用案例和理论解释。

Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操作:

分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
将集群中任一节点的请求路由到存有相关数据的节点
集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复

如何刻意练习?

第一,进行结果想象,也就是说,要尽可能具体地描绘你的目标。
第二,孤立问题,也就是当一个错误出现,要像拿着放大镜一样仔细拆解每一个和错误相关的因素,找到真正的问题所在。
第三,在格外需要纠正的弱项,难项上,给自己一个特别明确的行动命令。
第四,在自己做的事情上,尽可能地寻找第三方的客观意见,当然,这个第三方也包括你自己
第五点,最大化地确认和研究你的工具,根据他的原理和特性来优化你的练习方式。

同样的方法,在其他的领域也可以应用。尤其是在和表达相关的工作里面。我有个企业家朋友,他在企业要上市路演的时候来找我帮忙,所以我就让他用同样的方法把自己的演讲先录下来,让后让他从第三方的角度去观看。当他从第三方的角度去观看。当他从第三方的角度观看了之后,他发现,他的小动作特别多,还在一句话里居然说了九个“然后”。

如果你没有站在一个第三方的角度来审视自己,有些问题是很难感受到的,但是当你把自己抽离开来,这些问题其实变得非常明显。

单例模式:如何创建单一对象优化系统性能?

通常被称为 Double-Check,它可以大大提高支持多线程的懒汉模式的运行性能。
如果我们在程序启动后,一定会加载到类,那么用饿汉模式实现的单例简单又实用;
如果我们是写一些工具类,则优先考虑使用懒汉模式,因为很多项目可能会引用到 jar 包,但未必
会使用到这个工具类,懒汉模式实现的单例可以避免提前被加载到内存中,占用系统资源。

总结 : Double-Check 懒汉模式 性能

原型模式与享元模式:提升系统性能的利器

在有些场景下,我们需要重复创建多个实例,例如在循环体中赋值一个对象,此时我们就可以采用原型模式来优化对象的创建过程。

而在有些场景下,我们则可以避免重复创建多个实例,在内存中共享对象就好了

原型模式。

原型模式是通过给出一个原型对象来指明所创建的对象的类型,然后使用自身实现的克隆接口来复制这个原型对象,该模式就是用这种方式来创建出更多同类型的对象。使用这种方式创建新的对象的话,就无需再通过 new 实例化来创建对象了。这是因为Object 类的 clone 方法是一个本地方法,它可以直接操作内存中的二进制流,所以性能相对 new 实例化来说,更佳。

我们现在通过一个简单的例子来实现一个原型模式:

// 实现 Cloneable 接口的原型抽象类 Prototype
class Prototype implements Cloneable {
	
	 // 重写 clone 方法
    @Override
	public Prototype clone(){
		Prototype prototype = null;
		try{
			prototype = (Prototype)super.clone();
		}catch(CloneNotSupportedException e){
			e.printStackTrace();
		}
		return prototype;
	}
}
// 实现原型类
class ConcretePrototype extends Prototype{
	  public void show(){
        System.out.println(" 原型模式实现类 hashCode " + this.hashCode());
    }
}

public class Client {
	public static void main(String[] args){
		ConcretePrototype cp = new ConcretePrototype();
		for(int i=0; i< 10; i++){
			ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
			clonecp.show();
		}
	}
}

要实现一个原型类,需要具备三个条件:

实现 Cloneable 接口:Cloneable 接口与序列化接口的作用类似,它只是告诉虚拟机可
以安全地在实现了这个接口的类上使用 clone 方法。在 JVM 中,只有实现了 Cloneable
接口的类才可以被拷贝,否则会抛出 CloneNotSupportedException 异常。

重写 Object 类中的 clone 方法:在 Java 中,所有类的父类都是 Object 类,而 Object
类中有一个 clone 方法,作用是返回对象的一个拷贝。

在重写的 clone 方法中调用 super.clone():默认情况下,类不具备复制对象的能力,需
要调用 super.clone() 来实现。

通过 clone 方法复制的对象才是真正的对象复制,clone 方法赋值的对象完全是一个独立
的对象。刚刚讲过了,Object 类的 clone 方法是一个本地方法,它直接操作内存中的二进
制流,特别是复制大对象时,性能的差别非常明显。我们可以用 clone 方法再实现一遍以
上例子。

深拷贝和浅拷贝

在调用 super.clone() 方法之后,首先会检查当前对象所属的类是否支持 clone,也就是看
该类是否实现了 Cloneable 接口。

如果支持,则创建当前对象所属类的一个新对象,并对该对象进行初始化,使得新对象的成
员变量的值与当前对象的成员变量的值一模一样,但对于其它对象的引用以及 List 等类型
的成员属性,则只能复制这些对象的引用了。所以简单调用 super.clone() 这种克隆对象方
式,就是一种浅拷贝。

所以,当我们在使用 clone() 方法实现对象的克隆时,就需要注意浅拷贝带来的问题。我们
再通过一个例子来看看浅拷贝。

我们可以通过深拷贝来解决这种问题,其实深拷贝就是基于浅拷贝来递归实现具体的每个对 象。

适用场景:原型模式的实现原理,那到底什么时候我们要用它呢?

在一些重复创建对象的场景下,我们就可以使用原型模式来提高对象的创建性能。例如,我 在开头提到的,循环体内创建对象时,我们就可以考虑用 clone 的方式来实现。

package io.netty.example.design;

/**
 * @author linliangxuan
 * @date 2021/9/18 11:07
 */
// 定义学生类
class Student implements Cloneable{

    private String name; // 学生姓名
    private Teacher teacher; // 定义老师类

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    // 重写克隆方法
    @Override
    public Student clone() {
        Student student = null;
        try {
            student = (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student;
    }
}

package io.netty.example.design;

/**
 * @author linliangxuan
 * @date 2021/9/18 11:08
 */
// 定义老师类
class Teacher implements Cloneable{
    private String name; // 老师姓名
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name= name;
    }
    // 重写克隆方法,堆老师类进行克隆
    @Override
    public Teacher clone() {
        Teacher teacher= null;
        try {
            teacher= (Teacher) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return teacher;
    }
}

package io.netty.example.design;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;

/**
 * @author linliangxuan
 * @date 2021/9/18 11:15
 */
@Slf4j
public class PrototypeTheBestPratice {

    public static void main(String[] args) {
        bad(90000000);
        best(90000000);
    }

    public static void bad(int size){
        final long currentTimeMillis = System.currentTimeMillis();
        final ArrayList<Student> objects = new ArrayList<>(size);
        for(int i=0; i<size; i++){
            Student stu = new Student();
            stu.setName("aaaaaaaa");
            final Teacher teacher = new Teacher();
            stu.setTeacher(teacher);
            objects.add(stu);
        }
        log.info("花费时间 bad = {} ",System.currentTimeMillis() - currentTimeMillis);
    }

    public static void best(int size){
        final long currentTimeMillis = System.currentTimeMillis();
        final ArrayList<Student> objects = new ArrayList<>(size);
        Student stu = new Student();
        for(int i=0; i<size; i++){
            Student stu1 = (Student)stu.clone();
            stu1.setName("aaaaaaaa");
            objects.add(stu1);
        }
        log.info("花费时间 best = {} ",System.currentTimeMillis() - currentTimeMillis);
    }

}

时间是缩小了。空间的话是否能节省?为什么呢? 流?

在这里插入图片描述

除此之外,原型模式在开源框架中的应用也非常广泛。例如 Spring 中,@Service 默认都
是单例的。用了私有全局变量,若不想影响下次注入或每次上下文获取 bean,就需要用到
原型模式,我们可以通过以下注解来实现,@Scope(“prototype”)

享元模式

享元模式是运用共享技术有效地最大限度地复用细粒度对象的一种模式。

该模式中,以对象的信息状态划分,可以分为内部数据和外部数据。内部数据是对象可以共享出来的信息,这些信息不会随着系统的运行而改变;外部数据则是在不同运行时被标记了不同的值。

享元模式一般可以分为三个角色,
分别为 Flyweight(抽象享元类)、
抽象享元类通常是一个接口或抽象类,向外界提供享元对象的内部数据或外部数据;
ConcreteFlyweight(具体享元类)
具体享元类是指具体实现内部数据共享的类;
和 FlyweightFactory(享元工厂类)。
享元工厂类则是主要用于创建和管理享元对象的工厂类。

/**
 * @author linliangxuan
 * @date 2021/9/18 13:53
 */
// 抽象享元类
interface Flyweight {
    // 对外状态对象
    void operation(String name);
    // 对内对象
    String getType();
}
import java.util.HashMap;
import java.util.Map;

/**
 * @author linliangxuan
 * @date 2021/9/18 13:57
 */
public class FlyweightFactory {


    private static final Map<String, Flyweight> FLYWEIGHT_MAP = new HashMap<>();// 享元池
    public static Flyweight getFlyweight(String type) {
        if (FLYWEIGHT_MAP.containsKey(type)) {// 如果在享元池中存在对象,则直接获取
            return FLYWEIGHT_MAP.get(type);
        } else {// 在响应池不存在,则新创建对象,并放入到享元池
            ConcreteFlyweight flyweight = new ConcreteFlyweight(type);
            FLYWEIGHT_MAP.put(type, flyweight);
            return flyweight;
        }
    }

}

/**
 * @author linliangxuan
 * @date 2021/9/18 13:55
 */
public class ConcreteFlyweight implements Flyweight {
    private String type;
    public ConcreteFlyweight(String type) {
        this.type = type;
    }
    @Override
    public void operation(String name) {
        System.out.printf("[类型 (内在状态)] - [%s] - [名字 (外在状态)] - [%s]\n", type,name);
    }
    @Override
    public String getType() {
        return type;
    }
}

/**
 * @author linliangxuan
 * @date 2021/9/18 13:58
 */
public class Client {

    public static void main(String[] args) {
        Flyweight fw0 = FlyweightFactory.getFlyweight("a");
        Flyweight fw1 = FlyweightFactory.getFlyweight("b");
        Flyweight fw2 = FlyweightFactory.getFlyweight("a");
        Flyweight fw3 = FlyweightFactory.getFlyweight("b");
        fw1.operation("abc");
        System.out.printf("[结果 (对象对比)] - [%s]\n", fw0 == fw2);
        System.out.printf("[结果 (内在状态)] - [%s]\n", fw1.getType());
    }

}

在这里插入图片描述
观察以上代码运行结果,我们可以发现:如果对象已经存在于享元池中,则不会再创建该对
象了,而是共用享元池中内部数据一致的对象。这样就减少了对象的创建,同时也节省了同
样内部数据的对象所占用的内存空间。

适用场景:

享元模式在实际开发中的应用也非常广泛。例如 Java 的 String 字符串,在一些字符串常
量中,会共享常量池中字符串对象,从而减少重复创建相同值对象,占用内存空间。代码如
下:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1==s2);//true

还有,在日常开发中的应用。例如,线程池就是享元模式的一种实现;将商品存储在应用服
务的缓存中,那么每当用户获取商品信息时,则不需要每次都从 redis 缓存或者数据库中获
取商品信息,并在内存中重复创建商品信息了。

总结:在不得已需要重复创建大量同一对象时,我们可以使用原型模式,通过 clone 方法复制对
象,这种方式比用 new 和序列化创建对象的效率要高;在创建对象时,如果我们可以共用
对象的内部数据,那么通过享元模式共享相同的内部数据的对象,就可以减少对象的创建,
实现系统调优。

思考题:

单例模式和享元模式都是为了避免重复创建对象,两者的区别在哪?

回答:单例模式是针对某个类的单例,享元模式可以针对一个类的不同表现形式的单例,享元模
式是单例模式的超集。

享元模式可以再次创建对象 也可以取缓存对象
单例模式则是严格控制单个进程中只有一个实例对象
享元模式可以通过自己实现对外部的单例 也可以在需要的使用创建更多的对象 …

享元模式可以理解为一组单例模式

享元模式的实例也需要考虑线程安全哇?

回复: 需要的。共享数据尽量不要涉及到线程安全问题,否则就没有什么优势了。例如字符串
则利用了不可变性来避免线程安全问题。

首先,这两种设计模式的实现方式是不同的。我们使用单例模式是避免每次调用一个类实例
时,都要重复实例化该实例,目的是在类本身获取实例化对象的唯一性;而享元模式则是通
过一个共享容器来实现一系列对象的共享。
其次,两者在使用场景上也是有区别的。单例模式更多的是强调减少实例化提升性能,因此
它一般是使用在一些需要频繁创建和销毁实例化对象,或创建和销毁实例化对象非常消耗资
源的类中。

例如,连接池和线程池中的连接就是使用单例模式实现的,数据库操作是非常频繁的,每次
操作都需要创建和销毁连接,如果使用单例,可以节省不断新建和关闭数据库连接所引起的
性能消耗。而享元模式更多的是强调共享相同对象或对象属性,以此节约内存使用空间。

除了区别,这两种设计模式也有共性,单例模式可以避免重复创建对象,节约内存空间,享
元模式也可以避免一个类的重复实例化。总之,两者很相似,但侧重点不一样,假如碰到一
些要在两种设计模式中做选择的场景,我们就可以根据侧重点来选择。

new一个对象和clone一个对象,性能差在哪里呢?

回复: 一个对象通过new创建的过程为:
1、在内存中开辟一块空间;
2、在开辟的内存空间中创建对象;
3、调用对象的构造函数进行初始化对象。
而一个对象通过clone创建的过程为:
1、根据原对象内存大小开辟一块内存空间;
2、复制已有对象,克隆对象中所有属性值。
相对new来说,clone少了调用构造函数。如果构造函数中存在大量属性初始化或大对象,则使用
clone的复制对象的方式性能会好一些。

线程上下文设计模式

线程上下文是指贯穿线程整个生命周期的对象中的一些全局信息。例如,我们比较熟悉的
Spring 中的 ApplicationContext 就是一个关于上下文的类,它在整个系统的生命周期中
保存了配置信息、用户信息以及注册的 bean 等上下文信息。

在执行一个比较长的请求任务时,这个请求可能会经历很多层的方法调用,假设我们需要将
最开始的方法的中间结果传递到末尾的方法中进行计算,一个简单的实现方式就是在每个函
数中新增这个中间结果的参数,依次传递下去。

然而这种方式太笨拙了,每次调用方法时,都需要传入 Context 作为参数,而且影响一些
中间公共方法的封装。

那能不能设置一个全局变量呢?如果是在多线程情况下,需要考虑线程安全,这样的话就又 涉及到了锁竞争。

空间换时间(减少锁竞争)

除了以上这些方法,其实我们还可以使用 ThreadLocal 实现上下文。ThreadLocal 是线程
本地变量,可以实现多线程的数据隔离。ThreadLocal 为每一个使用该变量的线程都提供
一份独立的副本,线程间的数据是隔离的,每一个线程只能访问各自内部的副本变量。

Thread-Per-Message 设计模式

hread-Per-Message 设计模式就是每个消息一个线程的意思。例如,我
们在处理 Socket 通信的时候,通常是一个线程处理事件监听以及 I/O 读写,如果 I/O 读
写操作非常耗时,这个时候便会影响到事件监听处理事件。
但这里是有一个问题的,你发现了吗?
使用这种设计模式,如果遇到大的高并发,就会出现严重的性能问题。如果针对每个 I/O
请求都创建一个线程来处理,在有大量请求同时进来时,就会创建大量线程,而此时 JVM
有可能会因为无法处理这么多线程,而出现内存溢出的问题。
退一步讲,即使是不会有大量线程的场景,每次请求过来也都需要创建和销毁线程,这对系
统来说,也是一笔不小的性能开销。

面对这种情况,

我们可以使用线程池来代替线程的创建和销毁,这样就可以避免创建大量线 程而带来的性能问题,是一种很好的调优方法。

Worker-Thread 设计模式

Worker 是工人的意思,代表在 Worker Thread 设计模式中,会有一些工人(线
程)不断轮流处理过来的工作,当没有工作时,工人则会处于等待状态,直到有新的工作进
来。除了工人角色,Worker Thread 设计模式中还包括了流水线和产品。

这种设计模式相比 Thread-Per-Message 设计模式,可以减少频繁创建、销毁线程所带来
的性能开销,还有无限制地创建线程所带来的内存溢出风险.

总结

平时,如果需要传递或隔离一些线程变量时,我们可以考虑使用上下文设计模式。在数据库
读写分离的业务场景中,则经常会用到 ThreadLocal 实现动态切换数据源操作。但在使用
ThreadLocal 时,我们需要注意内存泄漏问题.当主线程处理每次请求都非常耗时时,就可能出现阻塞问题,这时候我们可以考虑将主线程业务分工到新的业务线程中,从而提高系统的并行处理能力。而 Thread-Per-Message 设计模式以及 Worker-Thread 设计模式则都是通过多线程分工来提高系统并行处理能力的设计模式。

生产者消费者模式

生产者与消费者是通过一个中间容器来解决强耦合关系,
并以此来实现不同的生产与消费速度,从而达到缓冲的效果。

Object 的 wait/notify/notifyAll 实现生产者消费者

基于 Object 的 wait/notify/notifyAll 与对象监视器(Monitor)实现线程
间的等待和通知,Monitor 的工作原理,借此我们可以得知,这种方式
实现的生产者消费者模式是基于内核来实现的,有可能会导致大量的上下文切换,所以性能
并不是最理想的。

Lock 中 Condition 的 await/signal/signalAll 实现生产者消费者

相对 Object 类提供的 wait/notify/notifyAll 方法实现的生产者消费者模式,我更推荐使用
java.util.concurrent 包提供的 Lock && Condition 实现的生产者消费者模式。在接口 Condition 类中定义了 await/signal/signalAll 方法,其作用与 Object 的wait/notify/notifyAll 方法类似,该接口类与显示锁 Lock 配合,实现对线程的阻塞和唤醒操作。

显示锁,显示锁 ReentrantLock 或 ReentrantReadWriteLock都是基于 AQS 实现的,而在 AQS 中有一个内部类 ConditionObject 实现了 Condition接口。

我们知道 AQS 中存在一个同步队列(CLH 队列),当一个线程没有获取到锁时就会进入到
同步队列中进行阻塞,如果被唤醒后获取到锁,则移除同步队列。

除此之外,AQS 中还存在一个条件队列,通过 addWaiter 方法,可以将 await() 方法调用
的线程放入到条件队列中,线程进入等待状态。当调用 signal 以及 signalAll 方法后,线
程将会被唤醒,并从条件队列中删除,之后进入到同步队列中。条件队列是通过一个单向链
表实现的,所以 Condition 支持多个等待队列。由上可知,Lock 中 Condition 的 await/signal/signalAll 实现的生产者消费者模式,是基于 Java 代码层实现的,所以在性能和扩展性方面都更有优势。

电商系统中经常会有抢购活动

在不分库分表的情况下,为了提高订单中扣除库存业务的性能以及吞吐量,我们就可以采用
生产者消费者模式来实现系统的性能优化。
创建订单等于生产者,存放订单的队列则是缓冲容器,而从队列中消费订单则是数据库扣除
库存操作。其中存放订单的队列可以极大限度地缓冲高并发给数据库带来的压力。

我们还可以基于消息队列来实现生产者消费者模式,如今 RabbitMQ、RocketMQ 都实现
了事务,我们只需要将订单通过事务提交到 MQ 中,扣除库存的消费方只需要通过消费
MQ 来逐步操作数据库即可。

生产者消费者模式除了可以做缓冲优化系统性能之外,它还可以应用在处理一些执行任务时 间比较长的场景中。

例如导出报表业务,用户在导出一种比较大的报表时,通常需要等待很长时间,这样的用户
体验是非常差的。通常我们可以固定一些报表内容,比如用户经常需要在今天导出昨天的销
量报表,或者在月初导出上个月的报表,我们就可以提前将报表导出到本地或内存中,这样
用户就可以在很短的时间内直接下载报表了。

思考题

我们可以用生产者消费者模式来实现瞬时高并发的流量削峰,然而这样做虽然缓解了消费方
的压力,但生产方则会因为瞬时高并发,而发生大量线程阻塞。
面对这样的情况,你知道有什么方式可以优化线程阻塞所带来的性能问题吗?

回复: 一致想到了限流,限流是非常必要的,无论我们的程序优化的如何,还是有上限
的,限流则是一种兜底策略。

1.生产消费模式用信号量也能玩。
2.生产者这边的优化思路应该是提高响应速度和增加资源。
提高响应速度就是尽量降低生产逻辑的耗时,
增加资源就是根据业务量为该生产者单独线程池并调整线程数。
至于限流和令牌桶感觉都是降级处理,属于规避阻塞场景而非解决阻塞场景,应该不在答案范围内
吧。

装饰器模式?

什么是装饰器模式?
装饰器模式包括了以下几个角色:接口、具体对象、装饰类、具体装饰类。
接口定义了具体对象的一些实现方法;具体对象定义了一些初始化操作,比如开头设计装修
功能的案例中,水电装修、天花板以及粉刷墙等都是初始化操作;
装饰类则是一个抽象类,主要用来初始化具体对象的一个类;
其它的具体装饰类都继承了该抽象类。

我们可以用生产者消费者模式来实现瞬时高并发的流量削峰,然而这样做虽然缓解了消费方
的压力,但生产方则会因为瞬时高并发,而发生大量线程阻塞。面对这样的情况,你知道有
什么方式可以优化线程阻塞所带来的性能问题吗?

无论我们的程序优化得有多么出色,只要并发上来,依然会出现瓶颈。虽然生产者消费者模
式可以帮我们实现流量削峰,但是当并发量上来之后,依然有可能导致生产方大量线程阻塞
等待,引起上下文切换,增加系统性能开销。这时,我们可以考虑在接入层做限流。

限流的实现方式有很多,例如,使用线程池、使用 Guava 的 RateLimiter 等。但归根结
底,它们都是基于这两种限流算法来实现的:漏桶算法和令牌桶算法。

漏桶算法是基于一个漏桶来实现的,我们的请求如果要进入到业务层,必须经过漏桶,漏桶
出口的请求速率是均衡的,当入口的请求量比较大的时候,如果漏桶已经满了,请求将会溢
出(被拒绝),这样我们就可以保证从漏桶出来的请求量永远是均衡的,不会因为入口的请
求量突然增大,致使进入业务层的并发量过大而导致系统崩溃。

令牌桶算法是指系统会以一个恒定的速度在一个桶中放入令牌,一个请求如果要进来,它需
要拿到一个令牌才能进入到业务层,当桶里没有令牌可以取时,则请求会被拒绝。Google
的 Guava 包中的 RateLimiter 就是基于令牌桶算法实现的。

我们可以发现,

漏桶算法可以通过限制容量池大小来控制流量,

而令牌算法则可以通过限制发放令牌的速率来控制流量。

在这里插入图片描述
讲故事比讲道理更能动员群众。领导者要讲四种领导力故事:我是谁,我们是谁,我们向何处去,我们为什么要变革。
在这里插入图片描述
我教你:领导者需要在五个层次上当老师,因此这句口诀有五种具体说法: 照我说的试试?或许会有不同呢? 我说给你听 我做给你看 你说怎么做 你为什么做

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

称为自己:
界定三个两难决绝:你该听从自己,还是听从他人?你该是追求结果,还是坚持原则?你该是坚持这个原则,还是坚持那个原则。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
情境领导力II 是一个由顾客为重心的领导培训项目,旨在帮助领导者通过情境分析和有效的沟通技巧来解决团队和顾客在工作中遇到的挑战。以下是一个情境领导力II 的案例: 在某家餐厅,经理李先生的团队遇到了一个顾客投诉的情况。投诉是一名顾客表示菜品的味道不符合期望,并且服务态度也让他感到不满。李先生意识到这是一个需要他积极介入的情况,他即刻使用情境领导力II 中学到的技巧,与服务员们进行了一次小组会议来讨论如何处理这个投诉。 在会议中,李先生鼓励团队成员们畅所欲言,以便他们能够更好地理解问题的本质。他表现出开放的姿态,不批评或指责任何人,而是帮助大家一起分析问题的根源。同时,他鼓励团队成员提出解决方案,并且不断强调顾客的满意度对于餐厅的重要性。在小组会议结束后,团队成员们重新调整了服务的流程,并且更加注重顾客的体验。 在接下来的几周内,李先生通过了解回访和收集反馈信息,证实团队的努力获得了成果。投诉次数显著下降,而顾客满意度也明显提升。李先生通过情境领导力II 中学习到的方法,成功地改善了团队的绩效,并让顾客感到更满意。 这个案例表明,情境领导力II 提供了一种有效的方法,帮助领导者在复杂的情况下有效地处理问题,并以团队的成功和顾客的满意度为重心进行领导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值