Skip to content

Commit

Permalink
feat: 更新文章
Browse files Browse the repository at this point in the history
  • Loading branch information
developer committed Nov 9, 2024
1 parent 7707275 commit 2d6281f
Show file tree
Hide file tree
Showing 7 changed files with 1,625 additions and 0 deletions.
File renamed without changes.
786 changes: 786 additions & 0 deletions _posts/2024-06-26-数据结构笔记.md

Large diffs are not rendered by default.

173 changes: 173 additions & 0 deletions _posts/2024-07-05-SPOOLing-模拟共享打印机.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
title: SPOOLing 模拟共享打印机
date: 2024-07-05 14:53:10 +0800
categories: [Study] # 目前有 Demo, Tutorial, Tech, Study
tags: [操作系统]
author: Zwei # 或 authors: [Zwei, another_author]
description: ""
image:
path: https://testingcf.jsdelivr.net/gh/bestZwei/imgs@master/picgo/2549f2e7795a40158330ace02089a915.png
permalink: '/w/spooling-printer' # 自定义永久链接
pin: false # 置顶文章
toc: true # 显示目录
comments: true # 允许评论
math: true # 启用数学公式
mermaid: true # 启用 Mermaid 图表
render_with_liquid: false # 禁用 Liquid 渲染
media_subpath: /blog/assets/ # 资源路径前缀
---

#### 什么是假脱机技术?

**假脱机技术**(Spooling)是一种在多道程序环境下,将IO操作与CPU操作分离的技术。在打印系统中,多个打印任务可以同时提交到打印队列中,由假脱机技术对这些任务进行管理和调度,实现**打印机的共享**使用,**每个程序都认为自己独占了打印机**。本课程设计旨在通过**Java可视化实现假脱机技术的共享打印机模拟**,让其他学习者直观地了解假脱机技术的工作原理和优势。

![4f27e3522f8536dd5ed3f.png](https://pics.sputnik.cloudns.ch/file/4f27e3522f8536dd5ed3f.png)

### 1. 如何模拟?

**下图展示了模拟过程(输出队列是输出井,假脱机管理器是管理程序)**

**通过事件监听器,用来处理用户界面的各种交互操作,如提交任务和重置打印队列的按钮。**

![5a534dbf34f8d1c4fb7cc.png](https://pics.sputnik.cloudns.ch/file/5a534dbf34f8d1c4fb7cc.png)

我使用一个**优先级阻塞队列****模拟打印任务的排队**过程,它可以视作逻辑上**磁盘缓冲区里的输出井**。每个任务按照优先级和时间戳进行排序。用户通过可视化界面提交打印任务,系统将为每个任务分配一个唯一的编号(ID),并将其加入到队列中。打印机模拟为一个单线程执行服务 ExecutorService,每当空闲,依次从队列中取出任务进行打印。打印过程中,系统会显示当前打印任务的信息,以及等待队列中的任务列表。用户还可以通过界面重置打印队列,**清空输出井里的任务**

在传统SPOOLing系统中,会为每个打印请求创建一个**请求表**,记录请求的详细信息。在这个模拟程序中,`PrintTask`类的实例实际上就扮演了打印请求表的角色,它包含了打印内容、优先级、唯一ID(相当于请求标识)等信息。通过`outputQueue`(等待打印的任务队列、输出井)来管理这些请求,模拟了将请求表挂到假脱机文件队列上的过程。

最终,通过为每个用户进程分配一个逻辑上的存储区,系统实现了对打印机的共享。每个用户都感觉到自己在独占打印机,实际上是系统在快速地为多个用户服务。

#### **数据结构说明**

1.打印任务类(PrintTask)

``` java
static int idCounter = 0;
// 静态变量,用于生成唯一的任务编号 (构造方法里 this.id = ++idCounter;)
private int id; // 任务编号
private String content; // 打印内容
private int priority; // 任务优先级
private long timestamp; // 任务提交时间戳

public PrintTask(String content, int priority) { ... }

// 构造方法及访问器方法...

```

2. 打印假脱机模拟类(PrintSpoolerSim)

```java
public class PrintSpoolerSim extends JFrame {
private PriorityBlockingQueue<PrintTask> outputQueue = new PriorityBlockingQueue<>(10, Comparator.comparingInt(PrintTask::getPriority).thenComparingLong(PrintTask::getTimestamp));
// ...
}
```

+ outputQueue:这是一个PriorityBlockingQueue类型的队列,用于存储等待打印的任务。它是一个优先级队列,根据任务的优先级和提交时间戳进行排序,确保高优先级的任务或先提交的任务能够优先得到处理。假设队列的大小被初始化为10,那么意味着最多可以同时存储10个任务。



**submitTask()**

![9e5deab921b34d7a9b27b.png](https://pics.sputnik.cloudns.ch/file/9e5deab921b34d7a9b27b.png)

**processTasks()**

![5de874408cebd20f0114b.png](https://pics.sputnik.cloudns.ch/file/5de874408cebd20f0114b.png)

**resetQueue()**![becfa62b21e73d687d410.png](https://pics.sputnik.cloudns.ch/file/becfa62b21e73d687d410.png)



### 2. PriorityBlockingQueue 的使用和优先级处理

**我是如何实现任务的优先级处理的?**

答:为了实现任务的优先级处理,我使用了 `PriorityBlockingQueue`。这个队列支持优先级排序,任务按照优先级和时间戳进行排序。我们在**创建队列时传入了一个比较器****先比较任务的优先级,如果优先级相同再比较时间戳**。这确保了即使在多线程环境下,高优先级的任务也能优先处理。

```java
private PriorityBlockingQueue<PrintTask> outputQueue = new PriorityBlockingQueue<>(10,
Comparator.comparingInt(PrintTask::getPriority).thenComparingLong(PrintTask::getTimestamp));
```

### 3. 线程安全和任务执行

**我的系统如何保证线程安全和任务的顺序执行?**

答:为了保证线程安全和任务的顺序执行,我使用了 `ExecutorService`,具体来说是 `SingleThreadExecutor`。这个执行器确保了任务是按顺序执行的,每次只运行一个任务,这避免了并发执行可能带来的问题。

```java
private ExecutorService printerService = Executors.newSingleThreadExecutor();
```

### 4. GUI实时更新机制

我使用了 `SwingUtilities.invokeLater` 方法。这个方法确保所有的界面更新操作都在事件调度线程上执行,这样可以避免线程冲突和界面冻结。例如,在添加任务或更新打印状态时,都使用了这种方法来确保界面的响应性和数据的一致性。

```java
SwingUtilities.invokeLater(() -> {
queueArea.append("任务提交: " + task.getContent() + ",优先级 " + task.getPriority() + ",任务编号 " + task.getId() + "\n");
updateWaitingQueueArea();
});
```

### 5. 异常处理和用户输入验证

在用户输入方面,我设置了输入验证来确保数据的有效性。例如,优先级必须是整数。如果用户输入无效,系统会通过对话框提示他们。运行过程中,我也添加了异常处理机制,比如在打印任务执行时捕获中断异常,以确保系统稳定运行并及时响应用户操作。

```java
try {
int priority = Integer.parseInt(priorityField.getText());
submitTask(content, priority);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "优先级必须是整数", "输入错误", JOptionPane.ERROR_MESSAGE);
}
```

### 6. 性能优化和未来改进方向

答:目前系统的性能能满足基本的使用需求,但在处理大量任务或高并发场景下可能会有性能瓶颈。未来,我打算引入更复杂的任务调度算法,比如基于预估打印时间的动态优先级调整。此外,为了适应多用户环境,我计划支持多台打印机并行处理任务,这可以通过配置多个线程池来实现。这样,系统的处理能力和效率将大大提高。

### 7. 代码展示、实际运行示例

**简单演示一下系统的实际运行情况**

+ 启动程序后,用户在上方的输入框中输入打印内容和优先级,点击提交按钮。任务会被添加到队列中,并显示在队列区。
+ 随后,系统会自动开始打印任务,每个字符打印间隔两秒。

+ 在打印过程中,打印区会实时更新显示当前打印的内容。

+ 用户也可以点击重置按钮,清空所有任务,包括正在执行的任务。

演示输入:

```
任务提交: 打印测试文本打印测试文本打印测试文本打印测试文本,优先级 1,任务编号 1
任务提交: 打印测试文本1,优先级 2,任务编号 2
任务提交: 打印测试文本2,优先级 2,任务编号 3
任务提交: 打印测试文本3,优先级 3,任务编号 4
任务提交: 打印测试文本4,优先级 1,任务编号 5
任务提交: 打印测试文本5,优先级 1,任务编号 6
任务提交: 打印测试文本6,优先级 2,任务编号 7
任务提交: 打印测试文本7,优先级 3,任务编号 8
任务提交: 打印测试文本8,优先级 4,任务编号 9
任务提交: 打印测试文本9,优先级 1,任务编号 10
任务提交: 打印测试文本10,优先级 1,任务编号 11
任务提交: 打印测试文本11,优先级 1,任务编号 12
任务提交: 打印测试文本12,优先级 3,任务编号 13
打印队列已重置
```



### **8. 参考文献**

1. Java API 文档 https://docs.oracle.com/javase/8/docs/api/

2. 《Java 核心技术 卷 I 基础知识》(第十版)凯 S. 霍斯特曼

3. 《Java 并发编程实战》布莱恩·戈茨

4. 《计算机操作系统》汤小丹等
5. mermaid 介绍文档,用于生成流程图 https://mermaid.js.org/intro/
121 changes: 121 additions & 0 deletions _posts/2024-07-24-Git多账号配置.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
---
title: Git多账号配置
date: 2024-07-23 15:12:10 +0800
categories: [Tutorial] # 目前有 Demo, Tutorial, Tech, Study
tags: [Git]
author: Zwei # 或 authors: [Zwei, another_author]
description: "Windows设备管理多个git账号"
image:
path: https://testingcf.jsdelivr.net/gh/bestZwei/imgs@master/picgo/3a9282f87f892c286c9a9ccebe9c95dd_1679484529_216.png
permalink: '/w/Git-Multi-Account-Configuration' # 自定义永久链接
pin: false # 置顶文章
toc: true # 显示目录
comments: true # 允许评论
math: true # 启用数学公式
mermaid: true # 启用 Mermaid 图表
render_with_liquid: false # 禁用 Liquid 渲染
media_subpath: /blog/assets/ # 资源路径前缀
---


# Git 多账号配置

在日常开发中,我们可能会遇到这样的情况:一台电脑上既需要管理多个的Git账号以处理不同的项目代码,或者跨平台登录Git存储库。如果每次提交或拉取代码时都临时修改配置,不仅操作繁琐,而且容易出错。本文将记录一次性配置的方法,实现多账号管理。



## 环境

- 操作系统:Windows

- 项目目录A:`D:/account1/`

- 项目目录B:`D:/account2/`



## 配置步骤

### 1. 修改全局Git配置文件

首先,打开全局Git配置文件`C:/Users/用户名/.gitconfig`,原始配置可能只设置了某一个Git用户名和邮箱:

```bash
[user]
name = 用户名
email = 邮箱
```

将上面的内容删去,修改为条件引入配置:

```bash
[includeIf "gitdir:D:/work/"]
path = .gitconfig-account1
[includeIf "gitdir:D:/personal/"]
path = .gitconfig-account2
```

### 2. 创建多个的Git配置文件

在用户目录下新建两个(或更多)文件,分别用于存放两个(或更多)和邮箱配置:

#### `C:/Users/用户名/.gitconfig-account1`

```bash
[user]
name = 用户名A
email = 邮箱A #选填
```

#### `C:/Users/用户名/.gitconfig-account2`

```bash
[user]
name = 用户名B
email = 邮箱B #选填
```

### 3. 生成SSH密钥

运行以下命令分别生成账号A和账号B的SSH密钥。`-f`参数可以指定生成的文件名,`account1_id_rsa`是账号A的,`account2_id_rsa`是账号B的。

```bash
# 第一个账号的 SSH
ssh-keygen -f c:/Users/用户名/.ssh/gitlab_id_rsa -t rsa -C name1

# 第二个账号的 SSH
ssh-keygen -f c:/Users/用户名/.ssh/github_id_rsa -t rsa -C name2
```

完成后会得到以下文件:

- `account1_id_rsa``account1_id_rsa.pub`
- `account2_id_rsa``account2_id_rsa.pub`

`account1_id_rsa.pub``account2_id_rsa.pub`的内容分别复制到GitLab、GitHub或其他Git存储库对应的SSH设置页面。

### 4. 配置SSH

新建`C:/Users/用户名/.ssh/config`文件,内容如下:

```bash
Host github-account1
HostName github.com #此处填你使用的Git存储库的域名
User git
IdentityFile C:\\Users\\用户名\\.ssh\\account1_id_rsa
PreferredAuthentications publickey

Host github-account2
HostName gitlab.com #此处填你使用的Git存储库的域名
User git
IdentityFile C:\\Users\\用户名\\.ssh\\account2_id_rsa
PreferredAuthentications publickey

```

至此,Git多账号管理配置完成。现在,您可以在`D:/account1/``D:/account2/`目录下,无需每次手动切换配置。



[参考文献](https://nikolausliu.github.io/2021-04-09/git%E5%A4%9A%E8%B4%A6%E5%8F%B7%E7%AE%A1%E7%90%86.html)

62 changes: 62 additions & 0 deletions _posts/2024-07-31-基于Deeplx的翻译网页.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: 基于 Deeplx 的翻译网页
date: 2024-07-31 21:03:12 +0800
categories: [Tutorial] # 目前有 Demo, Tutorial, Tech, Study
tags: [Cloudlfare, Deeplx, translate]
author: Zwei # 或 authors: [Zwei, another_author]
description: "LibreTranslator"
image:
path: https://pics.sputnik.cloudns.ch/file/bf4c270e2bfb23cc6a07e.png
permalink: '/w/deeplx-web' # 自定义永久链接
pin: false # 置顶文章
toc: true # 显示目录
comments: true # 允许评论
math: true # 启用数学公式
mermaid: true # 启用 Mermaid 图表
render_with_liquid: false # 禁用 Liquid 渲染
media_subpath: /blog/assets/ # 资源路径前缀
---

#### 项目地址:https://github.com/bestZwei/LibreTranslator

#### 效果展示:https://fy.is-a.dev

### 部署

#### 1、使用 Cloudflare Pages 部署

1. Fork 本仓库。
2. 登录到 [Cloudflare](https://www.cloudflare.com/) ,在 Cloudflare Dashboard 中,选择 "Pages"。
3. 点击 "Create a Project"。
4. 连接到您的 GitHub 存储库,并选择该项目。
5. 在 "Configure your build" 步骤中,使用以下设置:
- **Framework preset**:
- **Build command**: `npm run build`
- **Build directory**: `build`
6. 点击 "Save and Deploy"。

#### 2、使用 Vercel 部署

1. Fork 本仓库。
2. 登录到 Vercel,点击 "New Project"。
3. 连接到您的 GitHub 存储库,并选择该项目。
4. Vercel 会自动检测到您使用的是 React 项目。您可以使用默认设置。
5. 点击 "Deploy"。

#### 所有部署方式都要配置环境变量

1. **REACT_APP_DEEPLX_API_URL**: `https://api.deeplx.org/<api-key>` ,不带 `/translate`

用于存储 DeepLx API 的 URL,以便在请求翻译时使用。`<api-key> `可以从 https://connect.linux.do/ 获取。

或者你是Pro用户,参考 [DeepLx文档 ](https://deeplx.owo.network/endpoints/pro.html)使用 `/v1` 请求 ,`https://api.deeplx.org/v1`

2. **REACT_APP_PASSWORD(可选)**: 访问密码

用于存储访问口令,限制其他人使用你部署的翻译网页。

3. **NODE_OPTIONS**:`--openssl-legacy-provider`

这个变量用于配置 Node.js 的选项,通常用于解决某些依赖包的兼容性问题,不设置则可能部署失败。

4. **REACT_APP_API_TOKEN(可选)**:按需修改,如果你是**自建的DeepLx服务**,参考请求链接是 `REACT_APP_DEEPLX_API_URL/translate?token=REACT_APP_API_TOKEN`,填写这两个环境变量。
Loading

0 comments on commit 2d6281f

Please sign in to comment.