Java 面试十大烂问题

  1. 什么是面向对象

    面向对象编程(OOP)主要是基于四个原则:封装、集成、多态、抽象。

    这四个原则共同构成了面向对象编程的基础。在代码的提现上则会使得代码模块化、可重用以及更加容易维护。

    封装使得代码内部的细节实现得以屏蔽,隐藏了代码内部的复杂性,继承则可以使得代码重复使用以及职责单一化,多态则允许对象之间互相转换,抽象侧重于将复杂的业务模型化、简单化

  2. Java 中最快的搜索算法

    Java 中比较常见且最常使用的算法是二分搜索和 hash 搜索。二分搜索主要适用于已经有序的数组或者列表。时间复杂度是O(log n)。

    Java代码实现二分查找
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package com.toca.bjca;

    public class BinarySearchExample {
    public static int binarySearch(int[] array, int target) {
    int left = 0;
    int right = array.length - 1;

    while (left <= right) {
    int mid = left + (right - left) / 2;

    if (array[mid] == target) {
    return mid;
    } else if (array[mid] < target) {
    left = mid + 1;
    } else {
    right = mid - 1;
    }
    }

    return -1; // Target element not found
    }

    public static void main(String[] args) {
    int[] array = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
    int target = 23;

    int index = binarySearch(array, target);

    if (index != -1) {
    System.out.println("Element found at index: " + index);
    } else {
    System.out.println("Element not found");
    }
    }
    }

    hash 搜索则是基于 hash 值的定位进行查找数据。主要是使用 HashMap 或者 HashSet这种数据结构,时间复杂度是 O((1))。

    java 代码实现 Hash 搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("John", 25);
map.put("Jane", 30);
map.put("Alice", 42);
map.put("Bob", 35);

String key = "Jane";

if (map.containsKey(key)) {
int value = map.get(key);
System.out.println("Value for key " + key + ": " + value);
} else {
System.out.println("Key not found");
}
}

3 JDK 和 JRE 是什么

JDK 代表的是 Java 开发工具包,JRE 是 Java 的运行时环境。JDK 是一个软件包,包括 Java 开发所需的一些工具例如:编译器、调试器、Java API,JDK 中还包括 JRE。

JRE 则是Java运行时环境。但是不包含开发工具

4 谈谈多线程

多线程是指在单个应用程序中同时间可以运行一个以上的线程任务。线程是轻量级的执行单元,它允许任务同时执行,从而提高应用程序的执行性能和响应能力。多线程执行任务还可以更大限度的利用多核 CPU 实现并行的任务处理,例如 I/O 操等

Java 中的多线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args) {
// Create two threads
Thread thread1 = new Thread(new MyRunnable("Thread 1"));
Thread thread2 = new Thread(new MyRunnable("Thread 2"));
// Start the threads
thread1.start();
thread2.start();
}
static class MyRunnable implements Runnable {
private String threadName;

public MyRunnable(String threadName) {
this.threadName = threadName;
}
//process bus
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + ": " + i);
try {
Thread.sleep(1000); // Pause for 1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

5 java中创建对象的方法

在 Java 中创建对象的方法有四种:使用 new 关键字、调用 clone()、使用反射创建对象、使用反序列化创建对象。

Java 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
// Using the new keyword
MyObject obj = new MyObject();

// Cloning an object
MyObject obj2 = obj.clone();

// Creating an object using reflection
Class<MyObject> clazz = MyObject.class;
MyObject obj3 = clazz.newInstance();

// Creating an object through deserialization
ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"));
MyObject obj4 = (MyObject) in.readObject();

6比较 Java 中的接口和抽象类。为什么更喜欢接口而不是抽象类?

接口和抽象类都允许定义类的共同行为。然而,接口提供了纯粹的抽象,允许类实现多个接口,而一个类只能扩展一个抽象类。接口定义契约,从而实现组件之间的松散耦合。抽象类提供部分实现,并且可以具有实例变量、构造函数和非抽象方法。当类需要支持多种行为或创建公共 API 时,接口是首选。

7 解释一下Java中Comparator和Comparable接口的区别

Java中Comparator和Comparable都是用于对象比较的。 Comparable 接口由类实现,以定义其对象的自然顺序。它提供了一个 compareTo() 方法来比较对象。 Comparator 接口允许对可能没有自然排序的对象进行自定义比较逻辑。它提供了一个 compare() 方法来执行比较。虽然 Comparable 强加了自然排序,但 Comparator 允许灵活地定义不同的比较策略。

Java 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Person implements Comparable<Person> {
private String name;

public int compareTo(Person other) {
return this.name.compareTo(other.name);
}
}

// Comparator interface
public class AgeComparator implements Comparator<Person> {
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}

8HashMap 与 HashTable

HashMap和HashTable都是用来存储键值对的。然而,HashTable 是一个同步类,使其线程安全,但可能速度较慢。 HashMap 不是同步的,提供了更好的性能,但本质上不是线程安全的。 HashMap 允许空键和值,而 HashTable 不允许空值。在大多数情况下,除非明确要求线程安全,否则 HashMap 是首选

9 Java 中 LinkedList 和 List 接口的区别

List 接口是 Java Collections Framework 中的一个基本接口,表示有序集合。 LinkedList 是 List 接口的实现,它将元素存储在双向链表中。 LinkedList提供了高效的两端元素插入和删除,但随机访问速度较慢。 ArrayList 是另一种 List 实现,它将元素存储在动态调整大小的数组中,与 LinkedList 相比,提供更快的随机访问,但插入和删除速度更慢

10 解释一下Java中引用值和变量值的区别。

在 Java 引用值是指向对象内存地址的。它允许访问和操作对象的属性和方法。变量值则是变量所保存的实际值。对于原始数据类型(例如 int boolean)变量值是直接分配给变量的值。对于引用类型(例如 new User())变量值就是引用值指向内存地址。

Java 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.toca.bjca;

public class ReferenceValueVsVariableValueExample {
public static void main(String[] args) {
int variableValue = 10;
int anotherVariableValue = variableValue;

System.out.println("Variable Value: " + variableValue);
System.out.println("Another Variable Value: " + anotherVariableValue);

anotherVariableValue = 20;

System.out.println("Variable Value: " + variableValue);
System.out.println("Another Variable Value: " + anotherVariableValue);

Person person1 = new Person("John");
Person person2 = person1;

System.out.println("Person 1: " + person1.getName());
System.out.println("Person 2: " + person2.getName());

person2.setName("Jane");

System.out.println("Person 1: " + person1.getName());
System.out.println("Person 2: " + person2.getName());
}

static class Person {
private String name;

public Person(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
}

上述代码表明:变量的值是相互独立的,引用值指向内存地址中的一个对象。修改引用值则会影响到此对象的所有引用,因为内存地址发生了变化。

性能之巅-读书笔记(1)

system-wide analysis 意思是对整个系统进行的分析。

这个词语通常用在复杂的系统或组织上,表示要采取全面而综合的方式来分析这个系统。

例如:

  1. 对公司的system-wide analysis,以找出生产过程中的问题所在。

  2. 对城市交通系统进行system-wide analysis,以确定哪些地方出现拥堵。

  3. 对教育体系进行system-wide analysis,找出影响教学质量的因素。

  4. 对病人的健康问题进行system-wide analysis,不仅看身体症状,也要分析生活方式、工作环境等因素。

  5. 政府进行关于贫困问题的system-wide analysis,分析经济、社会、教育等各方面因素。

简单来说,system-wide analysis就是采取全面和综合的视角,从不同层面、不同方面来分析一个大系统,找出系统性的问题所在,并给出建议或解决方案。它强调问题的复杂性和系统性,而不仅仅局限在某个狭窄的视野或层面。

capacity planning 翻译为容量规划或能力规划,是指对一个系统或组织的生产能力进行预估和规划,以满足当前和未来的业务需求。

capacity planning 的主要目的是确保有充足的资源和能力来应对业务增长或客户需求的变化,避免因容量不足而影响业务运营。进行 capacity planning 通常会考虑以下几个方面:

  1. 分析历史需求模式,预测未来需求变化趋势。

  2. 评估现有设施、设备、人力等生产要素的能力和限制。

  3. 根据需求预测,计算所需要的新增产能。

  4. 制定容量扩充计划,如增加设备、场地、人员等。

  5. 确定所需资金投入,评估投资回报。

  6. 定期监控和审查已有容量,进行调整。

  7. 平衡好过剩和不足的风险。

Capacity planning 适用于各种系统,如生产系统、仓储系统、IT系统、服务系统等。实施容量规划可以提高资源利用率,控制成本,为业务扩张做好准备。它通常是企业战略规划的重要组成部分。

性能领域包括以下事情

  1. 设置性能目标和建立性能模型
  2. 基于软件或硬件原型进行性能特征归纳
  3. 对开发代码进行性能分析(软件整合之前)
  4. 执行软件非回归性测试(软件发布前或发布后)
  5. 针对软件发布版本的基准测试
  6. 目标环境中的概念验证(Proof-of-concept)测试
  7. 生产环境部署的配置优化
  8. 监控生产环境中运行的软件
  9. 特定问题的性能分析

Proof-of-concept 翻译为“概念证明”,意思是对一个想法、设计或方法的可行性进行验证和证明。

通常包含以下主要特征:

  1. 用最小可行的产品或方法来验证某一概念或理论是否可行。

  2. 目标是展示该概念在解决特定问题或需求方面的潜力和可行性。

  3. 可以是原型,也可以是模拟实验、模型等。重点在于获取验证该概念的有效性所需的预期数据。

  4. 如果结果满足预期,则提供继续投入研发的依据。如果不符合,则需要调整甚至放弃该概念。

  5. 整个过程充满试验性质,目标不是最终成品。

举例来说,一个新产品在上市前会先做Proof-of-concept,来证明该产品的核心技术和设计在功能和用户体验上是可行的。一个医疗项目也会在临床试验前进行Proof-of-concept,以验证该疗法的科学理论基础。

所以,Proof-of-concept对于验证新想法的可行性非常重要,可以在投入大量资源开发前检验风险。它是任何概念从理论到实践的重要一步。

负载分析(Load Analysis)和资源分析(Resource Analysis)都是对系统的性能和容量进行分析评估的方法。

负载分析主要是分析系统在正常或峰值负载下的运行状况,关键在于负载(Load)。

  • 它侧重对系统所承受的负载进行计量,如网络流量、并发用户请求、每秒交易量等。

  • 通过设定不同负载参数,模拟系统在不同负载下的性能表现。

  • 目的是确定系统的负载容量,防止超载,提供合理配置。

资源分析主要是分析系统所需要的各种资源状况,关键在于资源(Resource)。

  • 它侧重对系统所需的关键资源进行分析,如服务器、带宽、内存、存储等。

  • 对各种资源的供给与消耗情况进行测量和评估。

  • 目的是合理配置和调配资源,提供系统所需的资源支持。

简单来说,负载分析关注输入量,资源分析关注处理能力。它们通常要结合进行,才能全面评估系统的性能和容量,做出优化的配置和扩容方案。二者都是对系统的容量进行考量,但侧重点不同。

纳秒(ns):10-9秒[编辑]

1纳秒(nanoseconds)即1000皮秒;也叫纳秒、奈秒、诺秒、纤秒、那诺秒、毫微秒。

微秒(µs):10-6秒[编辑]

1微秒(microsecond)即1000纳秒。

毫秒(ms):10-3秒[编辑]

1毫秒(millisecond)即1000微秒。

  • 1毫秒 – 大部分电脑计算时间的基本单位。许多程式计算延迟的基本单位。
  • 2.4毫秒 – 鿔元素的半衰期。
  • 3毫秒 – 苍蝇 搧一次翅膀的时间。
  • 5毫秒 – 蜜蜂 搧一次翅膀的时间。

(s)[编辑]

国际单位制中时间的基本单位,本页面的单位基准。1秒即1000毫秒。

一般很少使用比秒更大的字头单位(如千秒等),而用小时 等。

  • 60秒 – 1分钟的长度。

延时(Latency)是一个常见的性能指标,在性能测试中起着非常重要的作用。

简单来说,延时是指系统处理一个请求或者完成一个操作所花费的时间。它反映了系统的响应快慢。常见的延时指标有:

  • 网络延时:数据从发送端传到接收端所花费的时间。反映了网络的传输速度。

  • 服务延时:服务端处理一个请求并返回响应结果所花费的时间。反映了服务的响应效率。

  • 事务延时:用户发起一个业务操作直到得到结果所花费的时间。反映了整个业务流程的执行效率。

影响延时的因素有:网络带宽、系统架构、代码优化、服务器性能等。延时过高会严重影响用户体验。

在性能测试中,关注延时指标可以帮助我们:

  • 定位系统瓶颈,发现性能问题所在。

  • 对比不同配置下的延时曲线,找出最优方案。

  • 设置延时阈值,避免响应过慢影响业务。

  • 模拟不同并发用户下的延时情况。

通过延时分析,可以持续优化系统性能,提升用户体验,这是每一个资深性能测试工程师必备的专业技能。

每秒发生的IO次数(IOPS)是评测存储系统性能的一个重要指标。

IOPS表示在一秒内系统能够执行的输入输出(Input/Output)操作总次数。输入输出操作包括读取和写入操作。

一般来说,IOPS值越高,说明存储系统能够处理的IO请求越多,性能也就越好。

影响IOPS的因素有:

  • 硬盘转速,如普通硬盘转速较慢,固态硬盘转速更快
  • 随机或顺序读取写入,随机IO性能较差
  • 队列深度,请求越多,等待处理的队列越长
  • 读取写入比例,读写比例不均衡也会降低IOPS

IOPS常见的应用场景:

  • 评估存储系统能力,是否满足业务需求
  • 对比不同存储配置的性价比
  • 定位存储性能瓶颈
  • 监控存储性能变化趋势

提高IOPS可以改善存储读写性能,提升系统整体响应速度。所以IOPS是一个非常重要的性能指标,需要关注和分析。

TCP Handshake

![TCP Handshake](https://raw.githubusercontent.com/onlywyt/wyt-pic/main/img/Kapture 2023-09-23 at 19.54.29.gif)

大宋词龙——辛稼轩

辛弃疾,字幼安,号稼轩居士。出生在被金国占领的宋朝领土——山东,但是抗金归宋。

辛弃疾是一个比苏轼更让我敬佩的词人。

辛弃疾这人我们大部分都是在课本上了解到他作为词人、文人的一面。我们的老师可能会讲:辛弃疾是宋朝豪放派的词人。但是仅仅一个豪放完全不能代表辛弃疾这个人。他的豪情壮志,他的勇谋双绝,他的爱国情怀都是无法简单用“豪放”二字能概括的。

我们都应该读读《生活与命运》

img

这本书刚到,我一动不动看了200页。眼珠子都快看瞎了还是舍不得合上它。

书里梁文道的序:1961年2月14日上午,苏联国家安全委员会的特务闯进来格罗斯曼的家,为的是“搜捕”一份书稿。结果他们不只是带走了书、相关笔记和草稿,甚至连打出这本书的打字机和碳纸都不放过,行动规格如同逮捕一个活人,只不过他们这次要逮捕的是一本书。

这实在是太令人印象深刻了。到底是一本什么样的作品会令当局如此的忌惮。

这本书我很早就听说过,没有读的原因很可笑——我看到俄罗斯那冗长奇怪变化多端的人名字就脑阔疼!

伟大的小说开头各有各的魅力。

“田野上雾气沉沉。顺着公路伸展开去的高压线上,闪烁着汽车车灯的反光。”

“在千百的俄罗斯农舍中,没有也不可能有两座完全一模一样的。凡是有生命的东西,都各有各的特性。”

书里的观点就是一个词——自由。生命在于自由。每个人都能过着自己想要的生活,而不是被迫过着被某些人设计好的生活。每个人都可以说自己想说的事,论自己想论的人,而不是脑袋里装着一个个禁词。

我们以前就经历过那样的日子——任何一句话都可能被揪住上纲上线的审问。我们为此受到了难以诉说的苦难。

现在都是21世纪了,”我“竟然不能成为“我”,“我”竟然不能有“独立”的脑袋。新时代,还是不喜欢有脑袋的人,他们有各种手段,恩威并施的将我们的脑袋拿走,把我们的脑袋换成他们的。让我们自己把自己的心拿出来,然后自己涂上属于他们的颜色。

读这本书的时候,我不自觉的会联想到自己。我就像一根草,虽然我有思想,但是我却是自然界最脆弱的东西。不仅仅经受不起狂风骤雨,就算是一条狗踏过来也能把我踩的头破血流甚至踩死。

我一直以为现在跟过去不一样了,高尚、真诚的人就应该像一颗颗闪烁的星星一样耀眼。但是我错了,现在还是跟原来一样——“真诚、善良的人都该死”。我原来一直幻想,这个世界会变的。变成那种——透明的、真诚的、鹿是鹿、马是马的时代。但是直到有一位像导师一样的人说——被折磨惨的都是读书人…..我才知道…..

最后,

这本书的腰封上竟然写着“当代的战争与和平”。这真的是太令人惊讶了。我要争取快点读完,然后再读一遍。

祝大家周末愉快

学习 SHELL

  1. 编写一个命令,它可以递归地查找文件夹中所有的HTML文件,并将它们压缩成zip文件。注意,即使文件名中包含空格,您的命令也应该能够正确执行
1
find . -type f -name "*.html" | xargs -d '\n' -I{} zip html_files.zip {}
  1. 编写两个bash函数 marcopolo 执行下面的操作。 每当你执行 marco 时,当前的工作目录应当以某种形式保存,当执行 polo 时,无论现在处在什么目录下,都应当 cd 回到当时执行 marco 的目录。 为了方便debug,你可以把代码写在单独的文件 marco.sh 中,并通过 source marco.sh命令,(重新)加载函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

# 保存当前工作目录
marco() {
export MARCO_DIR=$(pwd)
}

# 返回到 marco 保存的目录
polo() {
cd $MARCO_DIR
}
# 1.首先运行source marco.sh,然后在当前目录运行marco
# 2.cd 到任意目录,运行polo,就会返回到当时执行 `marco` 的目录

image-20230902212716936

  1. 编写一个命令或脚本递归的查找文件夹中最近使用的文件。更通用的做法,你可以按照最近的使用时间列出文件吗?
1
2
3
4
5
#!/bin/bash

type=$1 # m-modified时间 a-访问时间

find . -type f -print0 | xargs -0 stat -f '%${type}%t%S${type} %N' | sort -nr

我有自己的想法,我该死吗?

日本宣布开始排放福岛第一核电站因为2011年核事故而产生的核污水之后,我国再一次掀起了抢盐的风潮。我印象里最早一次国民级别的抢盐大战是在“非典时期”。

2003年无论是卖什么的小贩,都做起了食盐生意,并且很快从抢购食盐扩展到大米、食用油、调味品。为什么要疯狂的囤积食盐和一切与食盐有关的东西呢?

答案是当年的“非典型肺炎”让民众误以为是与“加碘盐”有关系。因此才疯狂的抢购。

那如今都2023年了,为什么还要抢盐呢?答案就是下面这幅图

image-20230830221438327

不知道是从哪儿流传出来的;碘片可以预防核辐射。

那么真相究竟是什么呢?

Java CompletableFuture Demo

1.Introduction

When working with asynchronous operations with Java,the CompletableFuture class offers a way to manage these operations in a more intuitive and structured manner.Two commonly used methods in this class for handling multiple asynchronous tasks are allOf()and join().In the artcle,we will study these two methods.

2.Combining Multiple CompletableFuture

2.1 Useing CompletableFuture.allOf().join()

The allOf()methods in CompletableFuture allows you to combine multiple asynchronous tasks and create a new CompletableFuture that completes when all of the input futures are completed.The join() methods is then used to block the current thread until all the input futures are completed.This is particularly useful when you have a collection of tasks that need to executed concurrently,and you want to wait for all of then to complete before proceeding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static void allOfDemo() {
//是用CompletableFuture的allOf方法实现一个例子
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 10);
//join方法用来阻塞当前线程,等待future1 future2 计算完成
CompletableFuture.allOf(future1, future2).join();
try {
Integer integer = future1.get();
Integer integer1 = future2.get();
System.out.println("result1: " + (integer));
System.out.println("result2: " + (integer1));
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}

2.2 Useing CompletableFuture.allOf().join() with multithreading

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private static void allDemoThread(){
ExecutorService executor1 = Executors.newSingleThreadExecutor();
ExecutorService executor2 = Executors.newSingleThreadExecutor();
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000); // 休眠3秒
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return 5;
}, executor1);

CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000); // 休眠3秒
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return 10;
}, executor2);

CompletableFuture.allOf(future1, future2).join();

try {
Integer integer = future1.get();
Integer integer1 = future2.get();
System.out.println("result1: " + (integer));
System.out.println("result2: " + (integer1));
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
} finally {
executor1.shutdown();
executor2.shutdown();
}
}

2.3 Using CompletableFuture.join()

On the other hand, the join() method on a single CompletableFuture is used to block the current thread and retrieve the result when the future is completed. This is useful when you have a single task that you want to wait for and obtain the result from. It’s important to note that unlike allOf(), join() is not used for combining multiple futures but for waiting on a single future.

1
2
3
4
5
 public static void main(String[] args) {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 42);
int result = future.join();
System.out.println("Result: " + result);
}

Error Handling

3.1 Handling Exceptions in CompletableFuture.allOf().join()

When using CompletableFuture.allOf().join(), exceptions that occur in any of the input futures are not directly propagated to the calling thread. Instead, the exceptions are typically stored within the individual futures. To handle exceptions in this scenario, you’ll need to retrieve them from the completed futures.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static void AllOfErrorHandlerDemo() {
//处理CompletableFuture.allOf().join()中的异常,使用CompletableFuture.allOf().join()方法等待所有的CompletableFuture完成
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5)
.exceptionally(ex -> {
System.err.println("Exception in future1: " + ex);
return 0; // Default value or recovery logic
});
CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
//异常
throw new RuntimeException("Something went wrong");
}).exceptionally(ex -> {
//异常处理
System.err.println("Exception in future2: " + ex);
return 0;
});
// 返回一个新的CompletableFuture,当所有的CompletableFuture都完成后,新的CompletableFuture完成
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2);
// join()方法等待future1和future2完成,然后打印结果
combinedFuture.join();
try {
int result1 = future1.get();
int result2 = (int) future2.get();
System.out.println("Result 1: " + result1);
System.out.println("Result 2: " + result2);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}

In this example, we’re using the .exceptionally() method to handle exceptions for each individual future. This allows us to log the exception and provide a default value or recovery logic if needed.

4 Conclusion

In conclusion,both CompletableFuture.allOf().join() and CompletableFuture.join() are valuable tools in the asynchronous programming toolkit. They serve different purposes: allOf().join() is for combining multiple futures and waiting for their completion, while join() is for waiting on a single future. Understanding their use cases, behavior, and performance implications can greatly enhance your ability to write efficient and responsive asynchronous code in Java.

Java CompletableFuture Demo

RSA加密算法中的公钥和密钥

密钥对

在昨天的文章RSA加密算法中提到了两个关键词——公钥、私钥。并且我们知道了,RSA 的加密就是求“明文的E次方 mod N”,解密是求“密文的D次方 mod N”。那么公式中的E、D、N这三个数就是生成的密钥对

这三个数字肯定不是随随便便就拿来用的,那样的话加密也太容易被破解了。它们有自己的生成方式。

RSA密钥对的生成

我们先来简单陈述一下RSA密钥对的生成步骤,这其中涉及到了一些数学原理,暂时先不用知道什么意思。因为我也一知半解

  1. 选择两个大的随机的质数 p 和 q
  2. p 和 q进行乘法运算得到的值就是 N,这个N 就是公钥和私钥mod的那个N
  3. 计算 φ(n), φ(n)= (p-1)*(q-1),其中φ是欧拉函数。暂时先不用知道什么是欧拉函数
  4. 现在来计算E,E 的计算规则是大于1但是小于 φ(n) 并且与 φ(n)互为质数。这个E就是公钥中的次幂数,暂时先不用知道什么是质数
  5. 现在来计算D,我们现在已经计算出来了公钥,E 和 N,那么D的计算规则需要满足以下条件:**(E * D) % φ(N) = 1**。为什么非要满足这个公式呢?因为只要数字D满足上述条件,通过E 和 N 进行加密的数据就可以通过D 和 N 进行解密

图解密码技术——RSA 公钥密码算法

公钥密码

公钥密码(Public-key cryptography)也称为非对称密码。是一种基于密钥对的密码体制。他需要两个密钥:公开密钥(public key )和私有密钥(private key)。一般使用公钥加密,私钥解密。

RSA

什么是 RSA ?

RSA 是一种公钥密码算法,是目前使用最广泛的公钥密码算法。RSA 三个字母的含义是:它的三位发明者的姓氏首字母——

Ron Rivest、Adi Shamir 和 Leonard Adleman(Rivest Shamir Adleman)。

在详细介绍 RSA 之前,需要先普及一点数学知识。

取模(余数)

我们知道在编程语言中有取模运算,取模运算就是求余数的运算。例如:

我们要计算 12 除以 5 的余数,运算过程为:

  1. 12 中有几个 5?答案是 2 个。因为 5 * 2 = 10, 5 * 3 = 15 。所以 12 中只包含 2 个 5
  2. 那么两个 5 相乘不够 12 ,还差多少呢?12 - 10 = 2,这个 2 就是余数。
  3. 那么上述过程用Java 编程语言表示就是:System.out.println(12 % 5);
  4. 这是简单的取模运算,那么我在来搞的复杂一点,12 这个数字可以分解为 2 * 2 * 2 * 2,也就是 24
  5. 我们来写一次取模的运算 24 mod 5

我们简单回顾了十几二十年前的知识,如果你理解了上面的过程那么你就已经为详细学习 RSA 打好了基础,因为 RSA 的加密解密过程所进行的就是上述运算

《美国四百年》——师夷长技

首先夸一下理想国。书本的装帧设计和印刷质量是真的好,捧在手里是真的有质感。


之前一段时间看了一点《獨立宣言:一部全球史》。书里介绍,从全球的视角从新审视独立宣言,举世闻名的《独立宣言》不仅仅是美国的立国文书,更为现代世界的文明立下了文明的基础。对世界各地造成了巨大的影响。如今在看这本《美国四百年》更是感触颇深。美国是世界上最强大,最文明的国家之一。美国的《独立宣言》更是被视为国家财富,宣言中的人生而平等、人被赋予了生命权、自由权和追求幸福的权利….每一个字都透着美国特有的光彩。