Java面试突击班(抓住金九银十) 持续更新中

news2024/11/13 9:59:37

文章目录

      • 1.Java中线程的实现方式?
      • 2. Java线程中的状态?
      • 3. Java中如何停止线程?
      • 4. Java中Sleep和wait方法的区别?
      • 5.扩展—— P5典型 P6典型 P7典型
      • 6.并发编程的三大特性
        • 原子性
          • 什么时并发编程得原子性
          • 保证并发编程得原子性
        • 可见性
          • 什么时可见性
          • 解决可见性的方式
        • 有序性
          • 什么是有序性
      • 7.什么是CAS,有什么优缺点
      • 8.Contended注解的作用

1.Java中线程的实现方式?

(1)继承Thread类,重写run方法。
启动线程是调用start()方法,这样会创建一个新的线程,并执行线程任务。
如果直接调用run()方法,这样会让当前线程执行run()方法中的业务逻辑。
代码如下:

public class P1 {
    public static void main(String[] args) {
        MyJob myJob = new MyJob();
        myJob.run();
        myJob.start();
        for (int j = 0; j < 2; j++) {
            System.out.println("start:j="+j);
        }
    }
}
class MyJob extends Thread{
    public void run(){
        for (int i = 0; i < 2; i++) {
            System.out.println("run:i="+i);
        }
    }
}

(2) 实现Runnable接口 重写run方法
Thread实现Runnable接口,因此两者追根究底一样。 在这里插入图片描述
但由于Java中是单继承,所以相比继承Thread类要好一些。
最常用的方式:

  • 匿名内部类:
Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("i=" + i);
                }
            }
        });
  • lambda方式:
  Thread thread = new Thread(()->{
            for (int i = 0; i < 10; i++) {
                System.out.println("lambda:"+i);
            } 
        });
    }

(3)实现Callable重写call方法,配合FutureTask
Callable一般用于有返回结果的非阻塞的执行方法。
非同步阻塞
如果想要返回一个结果,以上两种是没有办法是现实的。

public class P3 {
    public static void main(String[] args) throws ExecutionException,InterruptedException {
        Mycallables mycallables = new Mycallables();
        FutureTask futureTask = new FutureTask(mycallables);
        Thread thread = new Thread(futureTask);
        thread.start();
        //操作
        //要结果
        Object count = futureTask.get();
        System.out.println(count);
    }
}
class Mycallables implements Callable{

    @Override
    public Object call() throws Exception {
        int count = 0;
        for (int i = 0; i < 10; i++) {
            count +=1 ;
        }
        return count;
    }
}

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

(4) 基于线程池构建线程
追其底层,其实只有一只,就是实现Runnable接口

2. Java线程中的状态?

5种(一般针对操作系统层面):新建状态—start—就绪状态—(CPU调度)—运行状态—(wait()、sleep()、join())—等待状态——结束状态。
Java中给线程准备的6种状态:新建——运行\就绪状态(runnable)——阻塞状态(blocked)——等待(手动唤醒wating)——时间等待(timed_waiting)——结束
NEW:

//New
    public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread(()->{
	
        	});
   	 System.out.println(t1.getState());
}
 // Runnable 就绪/运行状态
     public static void main(String[] args) throws InterruptedException {
       Thread t2 = new Thread(()->{
           while(true){

           }
        });
        t2.start();
        Thread.sleep(500);
        System.out.println(t2.getState());
}
    //Blocked
     public static void main(String[] args) throws InterruptedException {
        Object object = new Object();
        Thread t3 = new Thread(()->{
            //t3下拿不到锁资源,导致变成Blocked状态
            synchronized (object){

            }
        });
        //main线程拿到obj的锁资源
         synchronized (object){
            t3.start();
            Thread.sleep(500);
            System.out.println(t3.getState());
         }
      }
      public static void main(String[] args) throws InterruptedException {
        // Waiting
        Object object0 = new Object();
        Thread t4 = new Thread(()->{
            synchronized (object0){
                try {
                    object0.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t4.start();
        Thread.sleep(500);
        System.out.println(t4.getState());
       }
  // Timed_Waiting
     public static void main(String[] args) throws InterruptedException {
        Object object1 = new Object();
        Thread t5 = new Thread(()->{
            synchronized (object1){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t5.start();
        Thread.sleep(500);
        System.out.println(t5.getState());
   }

3. Java中如何停止线程?

(1)stop方法(不推荐,但却是可以做到。过时了)
强制让线程结束的方法有很多,最常用的就是让run方法结束,如论是return结束,还是抛出异常结束,都可以

public static void main(String[] args) throws InterruptedException {
	Thread t1 = new Thread(()->{
		try{
			Thread.sleep(5000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	});
	t1.strat();
	Thread.sleep(5000);
	t1.stop();
	System.out.println(t1.getState());
}

(2)使用共享变量(很少会用)
这种方式用的不多,有的线程可能会通过死循环来保证一直运行。
咱们可以通过修改共享变量在破坏死循环,让线程退出循环,结束run方法

 static volatile boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            while(flag){
                // 处理任务
            }
            System.out.println("任务结束");
        });
        t1.start();
        Thread.sleep(500);
        flag = false;

(3)interrupt方式
休眠时也可以停掉

/*=============interrupt================*/
        //中断标记位 默认形况下 为false
        System.out.println(Thread.currentThread().isInterrupted());
        // 执行interrupt之后,再次查看打断信息
        Thread.currentThread().interrupt();
        // interrupt标记位:true
        System.out.println(Thread.currentThread().isInterrupted());
        // 返回当前线程,并归位为false interrupt标记位:true
        System.out.println(Thread.interrupted());
        // 已经归位了
        System.out.println(Thread.interrupted());

        //=======================================
        Thread t3 = new Thread(()->{
           while(!Thread.currentThread().isInterrupted()){
               // 处理业务
           }
            System.out.println("end");
        });
        t3.start();
        Thread.sleep(500);
        t3.interrupt();

4. Java中Sleep和wait方法的区别?

  • sleep属于Thread类中的static方法,wait 属于Object类的方法
  • sleep属于Timed_waiting,自动被唤醒;wait属于waiting,需要手动唤醒
  • sleep方法在持有锁时,执行,不会释放锁资源;wait在执行后,会释放锁资源
  • sleep方法在持有锁或者不持有锁时,执行;wait方法必须在持有锁时才可以被执行
    wait方法会将持有锁的线程从owner仍到WaitSet集合中,这个操作实在修改ObjectMonitor对象,如果没有持有synchronized锁的话,是无法操作ObjectMonitor对象的。

5.扩展—— P5典型 P6典型 P7典型

P5典型:解释一下什么是乐观锁、悲观锁、自旋锁、读写锁、排他锁、共享锁、统一锁、分段锁、行锁、表锁等。

  • 乐观锁:首先来看乐观锁,顾名思义,乐观锁就是持比较乐观态度的锁。就是在操作数据时非常乐观,认为别的线程不会同时修改数据,所以不会上锁,但是在更新的时候会判断在此期间别的线程有没有更新过这个数据。比如数据库提供的类似于write_condition机制,Java API 并发工具包下面的原子变量类就是使用了乐观锁的CAS来实现的。
    适用场景:它适用于写少读多的情况,也就是说减少操作冲突,这样可以省去锁竞争的开销,提高系统的吞吐量。
    坏事未必会发生,事后补偿
  • 悲观锁 :悲观锁就是持悲观态度的锁。就在操作数据时比较悲观,每次去拿数据的时候认为别的线程也会同时修改数据,所以每次在拿数据的时候都会上锁,这样别的线程想拿到这个数据就会阻塞直到它拿到锁。比如行锁、表锁、读锁、写锁,都是在操作之前先上锁,Java API中的synchronized和ReentrantLock等独占锁都是悲观锁思想的实现。
    适用场景:它适用于写多读少的情况。因为,如果还使用乐观锁的话,会经常出现操作冲突,这样会导致应用层会不断地Retry,反而会降低系统性能。
    坏事一定会发生,预先预防
  • 自旋锁:一种常见的乐观锁实现,CS锁
    • ABA问题(看似值没有改变,其实已经经过改变如:0-8-0)(解决方法:加版本< version、boolean >)
long sequence ;经历一个操作就要++一次
public class TestAtomicStampedReference {
    private static class Order {
        long sequence;
        long time;

        @Override
        public String toString() {
            return "Order{" +
                    "sequence=" + sequence +
                    ", time=" + time +
                    '}';
        }
    }

//    static AtomicStampedReference<Order> orderRef = new AtomicStampedReference<>(new Order(), 0);
    static AtomicMarkableReference<Order> orderRef = new AtomicMarkableReference<>(new Order(), false);

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                Order old = orderRef.getReference();
//                int stamp = orderRef.getStamp();

                Order o = new Order();
                o.sequence = old.sequence + 1;
               o.time = System.currentTimeMillis();

//               orderRef.compareAndSet(old,o,stamp,stamp+1);
                orderRef.compareAndSet(old,o,false,true);

            }).start();
        }
//            SleepHelper.sleepSeconds(1);
        System.out.println(orderRef.getReference());

    }
}

- 保障CAS操作的原则性问题(lock问题)
  • 排他锁:只有一个线程能访问代码
  • 共享锁:可以允许有多个线程访问代码
  • 读写锁
    - 读锁:读的时候,不允许写,但是允许同时读
    - 写锁:写的时候,不允许写,也不允许读(排他锁)
  • 统一锁:大粒度的锁
    - 锁定A等待B,锁定B等待A
    - A+B统一起来成为大锁 解决死锁问题
  • 分段锁:分成一段一段小粒度的锁
  • 间隙锁:是一个在 索引记录 之间的间隙上的锁

P6典型

  • 对于线程池的理解和运用
  • 如何理解线程池的7大参数?
ThreadPoolExecutor tpe = new ThreadPoolExecutor(2,4,60, 
                TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

在这里插入图片描述
1.corePoolSize: 核心线程数的大小
2.maximunPoolSize:最大线程数大小
3.keepAliveTime:生存时间
4. TimeUnit.SECONDS:生存时间的单位
5.ArrayBlockingQueue(4):任务队列(核心)
6.Executors.defaultThreadFactory():线程池产生的工厂(区分不同的线程抛出的不同异常)
7.RejectedExecutionHandler handler:拒绝策略
估计并发量,确定核心线程数,核心线程永远存在。如餐厅服务员,两个核心员工,消息队列长度为四个,当两个客户占用两个核心员工之后,则从外部调用临时员工(临时员工+核心员工=最大员工数),临时员工服务接下来的客户,之后再服务队列中的客户。(规则由程序来定)。《此中,员工对应线程,客户对应任务》
设置线程的数量能把cpu占满,是跟该线程的IO密集和CPU密集息息相关的。
当线程数全满,又有任务进来的时候,不能够丢掉的任务,可以对其进行持久化。默认有四个策略(jdk)。服务外面可以搭一个mq的集群,扔进mq中,当线程空闲,再拿出来。
有界队列:永远使用有界
无界:如链表队列,尽量不使用

P7典型

  • 什么是纤程/协程
  • 它和普通的Java线程有什么不同
  • 为什么它能提高效率
扩充一下:什么是线程、进程?
一个程序-可执行文件,一般程序在硬盘上,想执行时,从硬盘放入内存里,这是这个程序就是一个进程(为其分配进程空间)。若要运行起来,则需要在进程空间找到线程入口-主线程。
线程是一般称为程序运行的基本单元。
一个CPU一般跑一个线程
线程撕裂者/超线程

6.并发编程的三大特性

原子性

JMM(Java Memory Model)。不同的硬件和不同的操作系统在内存上的操作有一定的差异的。Java为了解决相同代码在不同操作系统上出现的各种问题,用JMM屏蔽掉各种硬件和操作系统带来的差异。
让Java的并发编程可以做到跨平台。
JMM规定所有变量都会存储在主内存中,在操作的时候,需要从主内存中复制一份到线程内存(CPU内存),在线程内部做计算。然后再写回主内存中(不一定)

什么时并发编程得原子性

原子性得定义:一个操作是不可分割得,不可中断得,一个线程再执行时,另一个线程不会影响到他.

保证并发编程得原子性

synchronized:可以在方法上追加synchronized关键字或者采用同步代码块得形式来保证原子性,synchronized可以让避免多线程同时操作临界资源,同一时间点,只会有一个线程正在操作临界资源。
CAS:compare and swap也就是比较和交换,他是一条CPU的并发原语。
他在替换内存的某个位置的值时,首先查看内存中的值与预期值是否一致,如果一致,执行替换操作。这个操作是一个原子性操作。
java中基于Unsafe的类提供了对CAS的操作的方法,JVM会帮助我们将方法实现CAS汇编指令。但是要清楚CAS只是比较和交换,在获取原值的这个操作上,需要你自己实现。
Lock锁
Lock锁在1.5之前,性能相比较synchronized好,1.6之后,synchronized做了优化,性能相差就不大了。如果涉及并发比较多时,推荐ReentrantLock,性能会更好。其底层主要通过lock和unlock来实现。
ThreadLocal
其实,原子性用ThreadLocal很难保证,因为一般原子性是为了避免多线程使用共享变量,从而带来线程不安全。
ThreadLocal保证原子性的方式,是不让多线程去操作临界资源,让每个线程去操作属于自己的数据。

可见性

什么时可见性

可见性问题是基于CPU位置出现的,CPU处理速度非常快,相对于CPU来说,去内存获取数据这个事情太慢了,CPU就提供了L1,L2,L3的三级缓存,每次去主内存拿完数据后,就会储存到CPU的三级缓存,每次去三级缓存拿数据,效率肯定会提升。
这就会带来问题,现在二点CPU都是多核的,每个线程的工作内存(CPU三级缓存)都是独立的,会告知每个线程中做修改时,只改自己额工作内存,没有及时的同步到主内存,导致数据不一致问题。

解决可见性的方式

volatile:修饰成员变量,使用该关键字,相当于告知CPU,对当前属性的操作,不允许使用CPU的缓存,必须去和主存内操作
volatile的内存语义:
- volatile属性被写:当写一个volatile变量,JMM会将当前线程对应的CPU缓存及时刷新到主内存中
- volatile属性被读:当读一个volatile变量,JMM会将对应的CPU缓存中的内存设置无效,必须去主内存中重新读取共享变量。
加了volatile修饰的属性,会在转为汇编之后,追加一个lock的前缀,CPU执行这个指令时,如果带有lock前缀会做两个事情:
- 将当前处理器缓存行的数据写回到主内存
- 这个写回的数据,在其他的CPU内核的缓存中,直接无效
synchronized:加锁的时候将数据,同步到主内存
Lock:与synchronized完全不同,synchronized是基于他的内存语义,在获取和释放锁时,对CPU缓存做一个同步到主内存的操作;而lock锁是基于volatile实现的,Lock锁内部再进行枷锁和释放时,会对一个由volatile修饰和state属性进行加减操作。
final:final和volatile不允许同时修饰一个属性,final修饰的属性不允许再被写了。

有序性

什么是有序性

在Java中,.java文件中的内容会被编译,再执行前需要再次转为CPU可以识别的指令,CPU再执行这些指令时,为了提升执行效率,在不影响最终结果的前提下(满需一些要求),会对指令进行重排。
指令乱序执行的原因,是为了尽可能的发挥CPU的性能。
as-if-serial:
happens-before:
程序次序规则(Program Order Rule):在一个线程内,按照控制流顺序,书写在前面的操作先行发生于书写在后面的操作。
管程锁定规则(Monitor Lock Rule):一个unlock操作先行发生于后面对同一个锁的lock操作。
volatile变量规则(Volatile Variable Rule):对一个volatile变量的写操作先行发生于后面对这个变量的读操作。
线程启动规则(Thread Start Rule):Thread对象start()方法先行发生于此线程的每一个动作。
线程终止规则(Thread Termination Rule):线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread.join()方法和Thread.isAlive()的返回值等手段检测线程是否已经终止执行。
线程中断规则(Thread Interruption Rule):对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测到是否有中断发生。
对象终结规则(Finalizer Rule) :一个对象的初始化完成(构造函数结束)先行发生于它的finalize()方法的开始。
传递性(Transitivity):如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。
volatile:

7.什么是CAS,有什么优缺点

CAS:compare and swap也就是比较和交换,他是一条CPU的并发原语。
他在替换内存的某个位置的值时,首先查看内存中的值与预期值是否一致,如果一致,执行替换操作。这个操作是一个原子性操作。
java中基于Unsafe的类提供了对CAS的操作的方法,JVM会帮助我们将方法实现CAS汇编指令。但是要清楚CAS只是比较和交换,在获取原值的这个操作上,需要你自己实现。
缺点:CAS只能保证对一个变量的操作是原子性的,无法实现对多行代码实现原子性。
AtomicStampedReference在CAS时,不但会判断原值,还会比较版本信息。

 public static void main(String[] args) {
        AtomicStampedReference<String>reference = new AtomicStampedReference<>("AAA",1);
        String oldValue = reference.getReference();
        int oldVersion = reference.getStamp();
        boolean b = reference.compareAndSet(oldValue,"B",oldVersion,oldVersion+1);
        System.out.println("修改版本1的:"+b);
        boolean c = reference.compareAndSet("b","c",1,1+1);
        System.out.println("修改版本2的:"+c);
    }

自旋时间过长问题:
- 可以指定CAS一共循环多少次,如果超过这个次数,直接失败/或者挂起线程。(自旋锁、自适应自旋锁)
- 可以在CAS一次失败后,将这个操作暂存起来,后面需要获取结果时,将暂存的操作全部执行,再返回最后的结果。

8.Contended注解的作用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/417235.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CSS】固定定位示例 ( 屏幕左右两侧广告栏 | 开发要点分析 | 代码示例 )

文章目录一、开发要点分析二、代码示例一、开发要点分析 实现下图样式 : 中间部分是网页内容 , 左右两侧是 固定广告栏 , 不管浏览器如何滚动 , 缩放 , 该左右两侧广告栏不变 ; 标签结构分析 : 上述页面中 , 中心的版心盒子 与 左侧广告栏 / 右侧广告栏 是兄弟关系 ; <div …

如何在rust中使用泛型,trait对象的总结以及kv sever(3)

可以说在 Rust 开发中&#xff0c;泛型编程是我们必须掌握的一项技能。在你构建每一个数据结构或者函数时&#xff0c;最好都问问自己&#xff1a;**我是否有必要在此刻就把类型定死&#xff1f;**是不是可以把这个决策延迟到尽可能靠后的时刻&#xff0c;这样可以为未来留有余…

谷歌的Bard和OpenAI的GPT4的对比

前言 随着上个月21日谷歌面向公众开放人工智能聊天机器人Bard的访问权限&#xff0c;同样是上个月的14日OpenAI为聊天机器人ChatGPT发布的最新语言模型&#xff1a;GPT-4的问世&#xff0c;可以说关于ChatGPT应用的推出进入了百家争鸣的情况&#xff0c;而且竞争变得激烈起来&a…

手把手教你Temporal Fusion Transformer——Pytorch实战

建立了一个关于能源需求预测的端到端项目&#xff1a; 如何为 TFT 格式准备我们的数据。 如何构建、训练和评估 TFT 模型。 如何获取对验证数据和样本外预测的预测。 如何使用built-in model的可解释注意力机制计算特征重要性、季节性模式和极端事件鲁棒性。 什么是Temporal F…

Prophet学习(二) 时序预测开源工具包Prophet介绍

目录 一、Prophet 简介 二、Prophet 适用场景 三、Prophet 算法的输入输出 四、Prophet 算法原理 五、与机器学习算法的对比 六、代码 6.1 依赖安装 6.2 预测demo 七、参考资料 八、官方链接&#xff1a; 九、案例链接&#xff1a; 一、Prophet 简介 Prophet是Faceb…

C++学习 Day1

目录 1. C关键字(C98) 2.命名空间 3. C输入&输出 1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 目前只是初学阶段&#xff0c;只是大致的了解&#xff0c;以后再深入研究。 2.命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&am…

C++中的类模版

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…

Linux驱动开发——高级I/O操作(一)

一个设备除了能通过读写操作来收发数据或返回、保存数据&#xff0c;还应该有很多其他的操作。比如一个串口设备还应该具备波特率获取和设置、帧格式获取和设置的操作;一个LED设备甚至不应该有读写操作&#xff0c;而应该具备点灯和灭灯的操作。硬件设备是如此众多&#xff0c;…

PDF怎么转CAD文件?(免费!高效转换方法汇总)

一般而言&#xff0c;PDF图纸是不能修改的。若需修改&#xff0c;则需将PDF转CAD&#xff0c;此时如何满足PDF转CAD的需求呢&#xff1f;今天&#xff0c;我将教你两种免费的PDF转CAD的方法&#xff0c;助力高效办公。 1.本地软件转换法 这是用本地软件转换方法&#xff0c;支…

【系统集成项目管理工程师】项目管理一般知识

&#x1f4a5;项目管理一般知识 一、什么是项目 1、项目定义 项目是为达到特定的目的&#xff0c;使用一定资源&#xff0c;在确定的期间内&#xff0c;为特定发起人提供独特的产品、服务或成果而进行的一系列相互关联的活动的集合。项目有完整的生命周期&#xff0c;有开始…

Dubbo(超级无敌认真好用,万字收藏篇!!!!)

文章目录Dubbo前言大型互联网架构目标集群和分布式集群分布式架构演进1 Dubbo概述1.1 Dubbo概念1.2 Dubbo架构图2 Dubbo快速入门2.1 Zookeeper的安装2.2 springBoot整合DubboZookeeper2.2.1 创建项目Dubbo--provider2.2.2 创建项目Dubbo--consumer2.2.3 测试3 Dubbo高级特性3.1…

可视化 | Flask+Pyecharts可视化模板

文章目录&#x1f3f3;️‍&#x1f308; 1. 系统说明界面&#x1f3f3;️‍&#x1f308; 2. 柱状图示例界面&#x1f3f3;️‍&#x1f308; 3. 饼状图示例界面&#x1f3f3;️‍&#x1f308; 4. 折现图示例界面&#x1f3f3;️‍&#x1f308; 5. 散点图示例界面&#x1f3…

人工智能(Pytorch)搭建transformer模型,真正跑通transformer模型,深刻了解transformer的架构

大家好&#xff0c;我是微学AI&#xff0c;今天给大家讲述一下人工智能(Pytorch)搭建transformer模型&#xff0c;手动搭建transformer模型&#xff0c;我们知道transformer模型是相对复杂的模型&#xff0c;它是一种利用自注意力机制进行序列建模的深度学习模型。相较于 RNN 和…

【数据结构Java】--图、BFS、DFS、拓扑结构

目录 一、图&#xff08;Graph&#xff09; 1.概念 2.有向图 3.出度、入度 4.无向图 5.简单图、多重图 6.无向完全图 7.有向完全图 8.有权图 9.连通图 10.连通分量&#xff08;无向图&#xff09; 11.强连通图&#xff08;有向图&#xff09; 12.强连通分量 13.邻接矩…

微服务架构-服务网关(Gateway)-权限认证(分布式session替代方案)

权限认证-分布式session替代方案 前面我们了解了Gateway组件的过滤器&#xff0c;这一节我们就探讨一下Gateway在分布式环境中的一个具体用例-用户鉴权。 1、传统单应用的用户鉴权 从我们开始学JavaEE的时候&#xff0c;就被洗脑式灌输了一种权限验证的标准做法&#xff0c;…

Adobe全新AI工具引关注,Adobe firefly助力创作更高效、更有创意

原标题&#xff1a;Adobe全新AI工具引关注&#xff0c;Adobe firefly&#xff08;萤火虫&#xff09;助力创作更高效、更有创意。 以ChatGPT为首的生成式AI、AIGC等工具的战局正如火如荼的进行中..... 除了微软、百度的聊天机器人和一些初创公司的AI画图工具令人惊艳&#xff…

Greenplum数据库执行器——PartitionSelector执行节点

为了能够对分区表有优异的处理能力&#xff0c;对于查询优化系统来说一个最基本的能力就是做分区裁剪partition pruning&#xff0c;将query中并不涉及的分区提前排除掉。如下执行计划所示&#xff0c;由于单表谓词在parititon key上&#xff0c;在优化期间即可确定哪些可以分区…

003:Mapbox GL设定不同的投影方式

第003个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中设定不同的投影方式 。默认情况下为Mercator投影,或者设置为null或者undefined时候,显示为Mercator投影。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源…

【分享】维格表集成易聊实现线索自动化,减少流失率

公司•介绍 北京某职业教育公司专注行业发展、国际就业、留学、移民咨询。秉承专业性至上的原则&#xff0c;与行业内专家、高等学府以及产业集团合作&#xff0c;并邀请各领域专家组建了强大的专委会团队&#xff0c;为公司的业务开展提供专业性支持。 客户•遇到的问题 作为…

【Java面试八股文宝典之MySQL篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day23

大家好&#xff0c;我是陶然同学&#xff0c;软件工程大三即将实习。认识我的朋友们知道&#xff0c;我是科班出身&#xff0c;学的还行&#xff0c;但是对面试掌握不够&#xff0c;所以我将用这100多天更新Java面试题&#x1f643;&#x1f643;。 不敢苟同&#xff0c;相信大…