技术标签: 算法 进程 c语言及其进阶 c语言 操作系统 进程调度算法 数据结构
前言:本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解,完整代码放在文章末尾,欢迎大家自行拷贝调用
目录
typedef struct program
{
char name[20];
int running_time;
int enter_time;
int priority;
int done_time; //用于时间片轮转
int copyRunning_time; //用于时间片轮转
int start_time;
program* next;
} Program;
typedef struct programQueue
{
program* firstProg;
program* LastProg;
int size;
} programQueue;
顾名思义,先来后到,每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。但是当一个长作业先运行了,那么后面的短作业等待的时间就会很长,不利于短作业。FCFS 对长作业有利,适用于 CPU 繁忙型作业的系统,而不适用于 I/O 繁忙型作业的系统。
//FCFS先来先服务算法
void FCFS(program pro[], int num)
{
printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num); //按照进入顺序排序
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
int time = pro[0].enter_time;
int pronum = 1; //记录当前的进程
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); //从进程队列中取出进程
if (time < curpro->enter_time)
time = curpro->enter_time;
int done_time = time + curpro->running_time;
int T_time = done_time - curpro->enter_time;
sum_T_time += T_time;
float QT_time = T_time / (curpro->running_time + 0.0);
sum_QT_time += QT_time;
for (int tt = time; tt <= done_time && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
time += curpro->running_time;
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}
最短作业优先调度算法会优先选择运行时间最短的进程来运行,这有助于提高系统的吞吐量。这显然对长作业不利,很容易造成一种极端现象。比如,一个长作业在就绪队列等待运行,而这个就绪队列有非常多的短作业,那么就会使得长作业不断的往后推,周转时间变长,致使长作业长期不会被运行。
//短作业优先算法
void SJF(program pro[], int num)
{
printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num);
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
int time = pro[0].enter_time;
int pronum = 1; //记录当前的进程
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); //从进程队列中取出进程
if (time < curpro->enter_time)
time = curpro->enter_time;
int done_time = time + curpro->running_time;
int T_time = done_time - curpro->enter_time;
float QT_time = T_time / (curpro->running_time + 0.0);
sum_T_time += T_time;
sum_QT_time += QT_time;
int pre = pronum;
for (int tt = time; tt <= done_time && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pronum++;
}
}
sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
for (int i = pre; i < pronum; i++)
{
//将进程链入队列
EnterQueue(queue, &pro[i]);
}
pre = pronum;
printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
time += curpro->running_time;
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / num);
}
进程的优先级可以分为,静态优先级或动态优先级:
该算法也有两种处理优先级高的方法,非抢占式和抢占式:
但是依然有缺点,可能会导致低优先级的进程永远不会运行
//优先权高者优先(HPF)
void HPF(program pro[], int num)
{
printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num);
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
int time = pro[0].enter_time;
int pronum = 1; //记录当前的进程
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); //从进程队列中取出进程
if (time < curpro->enter_time)
time = curpro->enter_time;
int done_time = time + curpro->running_time;
int T_time = done_time - curpro->enter_time;
float QT_time = T_time / (curpro->running_time + 0.0);
sum_T_time += T_time;
sum_QT_time += QT_time;
int pre = pronum;
for (int tt = time; tt <= done_time && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pronum++;
}
}
sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
for (int i = pre; i < pronum; i++)
{
//将进程链入队列
EnterQueue(queue, &pro[i]);
}
pre = pronum;
printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
time += curpro->running_time;
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}
每个进程被分配一个时间段,称为时间片,即允许该进程在该时间段中运行。如果时间片用完,进程还在运行,那么将会把此进程从 CPU 释放出来,并把 CPU 分配另外一个进程;如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换;如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率;如果设得太长又可能引起对短作业进程的响应时间变长。
//时间片轮转(RR)
void RR(program pro[], int num)
{
printf("请输入时间片大小");
int timeslice; scanf("%d", ×lice);
printf("进程 到达时间 服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num);
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
pro[0].start_time = pro[0].enter_time;
EnterQueue(queue, &pro[0]);
int time = 0;
int pronum = 1;
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); // 从队列中取出头节点
if (time < curpro->enter_time)
time = curpro->enter_time;
if (timeslice >= curpro->running_time)
{
// 如果剩余时间小于时间片 则此任务完成
for (int tt = time; tt <= time + curpro->running_time && pronum < num; tt++)
{
// 模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pro[pronum].start_time = tt;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
time += curpro->running_time;
curpro->running_time = 0;
curpro->done_time = time;
int T_time = curpro->done_time - curpro->start_time;
float QT_time = T_time / (curpro->copyRunning_time + 0.0);
sum_T_time += T_time;
sum_QT_time += QT_time;
printf("%s\t%d\t%d\t %d\t %d\t %d\t %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
curpro->start_time, curpro->done_time, T_time, QT_time);
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
pro[pronum].start_time = pro[pronum].enter_time;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
continue;
}
for (int tt = time; tt <= time + timeslice && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pro[pronum].start_time = tt;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
time += timeslice;
curpro->running_time -= timeslice;
EnterQueue(queue, curpro); //当前程序未完成 继续添加到队列中
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
pro[pronum].start_time = pro[pronum].enter_time;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}
我们分三个文件进行操作,当然大家也可以把三个文件按顺序放在一个文件里面进行操作
course.h: 结构体的包含以及函数的声明
course.cpp: 函数的具体实现
test.cpp: 主函数用于调用其余文件函数
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
typedef struct program
{
char name[20];
int running_time;
int enter_time;
int priority;
int done_time; //用于时间片轮转
int copyRunning_time; //用于时间片轮转
int start_time;
program* next;
} Program;
typedef struct programQueue
{
program* firstProg;
program* LastProg;
int size;
} programQueue;
//初始化
void Queueinit(programQueue* queue);
//打印
void print(program pro[], int num);
//打印队列
void printQueue(programQueue* queue);
//加入进程队列
void EnterQueue(programQueue* queue, program* pro);
//查询
program* poll(programQueue* queue);
//输入
void inputProgram(program pro[], int num);
//根据时间排序
void sortWithEnterTime(program pro[], int num);
//FCFS先来先服务算法
void FCFS(program pro[], int num);
//根据长度排序
void sortWithLongth(program pro[], int start, int end);
//短作业优先算法
void SJF(program pro[], int num);
//根据优先级排列
void sortWithPriority(program pro[], int start, int end);
//优先权高者优先(HPF)
void HPF(program pro[], int num);
//时间片轮转(RR)
void RR(program pro[], int num);
//选择菜单
void choiceMenu();
#define _CRT_SECURE_NO_WARNINGS 1
#include "course.h"
//初始化
void Queueinit(programQueue* queue)
{
if (queue == NULL)
{
return;
}
queue->size = 0;
queue->LastProg = (program*)malloc(sizeof(program));
queue->firstProg = queue->LastProg;
}
//打印
void print(program pro[], int num)
{
for (int i = 0; i < num; i++)
{
printf("%d ", pro[i].enter_time);
}
}
//打印输出队列
void printQueue(programQueue* queue)
{
program* p = queue->firstProg->next;
while (p != NULL)
{
printf("%s ", p->name);
p = p->next;
}
printf("\n");
}
//加入进程队列
void EnterQueue(programQueue* queue, program* pro)
{
queue->LastProg->next = (program*)malloc(sizeof(program));
queue->LastProg = queue->LastProg->next;
queue->LastProg->enter_time = pro->enter_time;
memcpy(queue->LastProg->name, pro->name, sizeof(pro->name));
queue->LastProg->priority = pro->priority;
queue->LastProg->running_time = pro->running_time;
queue->LastProg->copyRunning_time = pro->copyRunning_time;
queue->LastProg->start_time = pro->start_time;
queue->size++;
}
//查询
program* poll(programQueue* queue)
{
program* temp = queue->firstProg->next;
if (temp == queue->LastProg)
{
queue->LastProg = queue->firstProg;
queue->size--;
return temp;
}
queue->firstProg->next = queue->firstProg->next->next;
queue->size--;
return temp;
}
//输入
void inputProgram(program pro[], int num)
{
for (int i = 0; i < num; i++)
{
program prog;
printf("请输入第%d个进程的名字,到达时间,服务时间,优先级\n", i + 1);
scanf("%s", prog.name);
scanf("%d", &prog.enter_time);
scanf("%d", &prog.running_time);
prog.copyRunning_time = prog.running_time;
scanf("%d", &prog.priority);
pro[i] = prog;
}
}
//根据时间排序
void sortWithEnterTime(program pro[], int num)
{
for (int i = 1; i < num; i++)
{
for (int j = 0; j < num - i; j++)
{
if (pro[j].enter_time > pro[j + 1].enter_time)
{
program temp = pro[j];
pro[j] = pro[j + 1];
pro[j + 1] = temp;
}
}
}
}
//FCFS先来先服务算法
void FCFS(program pro[], int num)
{
printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num); //按照进入顺序排序
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
int time = pro[0].enter_time;
int pronum = 1; //记录当前的进程
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); //从进程队列中取出进程
if (time < curpro->enter_time)
time = curpro->enter_time;
int done_time = time + curpro->running_time;
int T_time = done_time - curpro->enter_time;
sum_T_time += T_time;
float QT_time = T_time / (curpro->running_time + 0.0);
sum_QT_time += QT_time;
for (int tt = time; tt <= done_time && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
time += curpro->running_time;
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}
//根据长度排序
void sortWithLongth(program pro[], int start, int end)
{
int len = end - start;
if (len == 1) return;
for (int i = 1; i < len; i++) {
for (int j = start; j < end - i; j++)
{
if (pro[j].running_time > pro[j + 1].running_time)
{
program temp = pro[j];
pro[j] = pro[j + 1];
pro[j + 1] = temp;
}
}
}
}
//短作业优先算法
void SJF(program pro[], int num)
{
printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num);
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
int time = pro[0].enter_time;
int pronum = 1; //记录当前的进程
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); //从进程队列中取出进程
if (time < curpro->enter_time)
time = curpro->enter_time;
int done_time = time + curpro->running_time;
int T_time = done_time - curpro->enter_time;
float QT_time = T_time / (curpro->running_time + 0.0);
sum_T_time += T_time;
sum_QT_time += QT_time;
int pre = pronum;
for (int tt = time; tt <= done_time && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pronum++;
}
}
sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
for (int i = pre; i < pronum; i++)
{
//将进程链入队列
EnterQueue(queue, &pro[i]);
}
pre = pronum;
printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
time += curpro->running_time;
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / num);
}
//根据优先级排列
void sortWithPriority(program pro[], int start, int end)
{
int len = end - start;
if (len == 1) return;
for (int i = 1; i < len; i++)
{
for (int j = start; j < end - i; j++)
{
if (pro[j].priority > pro[j + 1].priority)
{
program temp = pro[j];
pro[j] = pro[j + 1];
pro[j + 1] = temp;
}
}
}
}
//优先权高者优先(HPF)
void HPF(program pro[], int num)
{
printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num);
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
int time = pro[0].enter_time;
int pronum = 1; //记录当前的进程
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); //从进程队列中取出进程
if (time < curpro->enter_time)
time = curpro->enter_time;
int done_time = time + curpro->running_time;
int T_time = done_time - curpro->enter_time;
float QT_time = T_time / (curpro->running_time + 0.0);
sum_T_time += T_time;
sum_QT_time += QT_time;
int pre = pronum;
for (int tt = time; tt <= done_time && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pronum++;
}
}
sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
for (int i = pre; i < pronum; i++)
{
//将进程链入队列
EnterQueue(queue, &pro[i]);
}
pre = pronum;
printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
time += curpro->running_time;
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}
//时间片轮转(RR)
void RR(program pro[], int num)
{
printf("请输入时间片大小");
int timeslice; scanf("%d", ×lice);
printf("进程 到达时间 服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
sortWithEnterTime(pro, num);
programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
Queueinit(queue);
pro[0].start_time = pro[0].enter_time;
EnterQueue(queue, &pro[0]);
int time = 0;
int pronum = 1;
float sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0)
{
program* curpro = poll(queue); // 从队列中取出头节点
if (time < curpro->enter_time)
time = curpro->enter_time;
if (timeslice >= curpro->running_time)
{
// 如果剩余时间小于时间片 则此任务完成
for (int tt = time; tt <= time + curpro->running_time && pronum < num; tt++)
{
// 模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pro[pronum].start_time = tt;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
time += curpro->running_time;
curpro->running_time = 0;
curpro->done_time = time;
int T_time = curpro->done_time - curpro->start_time;
float QT_time = T_time / (curpro->copyRunning_time + 0.0);
sum_T_time += T_time;
sum_QT_time += QT_time;
printf("%s\t%d\t%d\t %d\t %d\t %d\t %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
curpro->start_time, curpro->done_time, T_time, QT_time);
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
pro[pronum].start_time = pro[pronum].enter_time;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
continue;
}
for (int tt = time; tt <= time + timeslice && pronum < num; tt++)
{
//模拟进程的执行过程
if (tt >= pro[pronum].enter_time)
{
// 统计从此任务开始到结束之间有几个进程到达
pro[pronum].start_time = tt;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
time += timeslice;
curpro->running_time -= timeslice;
EnterQueue(queue, curpro); //当前程序未完成 继续添加到队列中
if (queue->size == 0 && pronum < num)
{
//防止出现前一个进程执行完到下一个进程到达之间无进程进入
pro[pronum].start_time = pro[pronum].enter_time;
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}
//选择菜单
void choiceMenu()
{
printf("请选择进程调度算法:\n");
printf("1.先来先服务算法\n");
printf("2.短进程优先算法\n");
printf("3.高优先级优先\n");
printf("4.时间片轮转算法\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"course.h"
int main()
{
int proNum = 5; //5个进程
program pro[5];
inputProgram(pro, proNum);
choiceMenu();
int choice;
do
{
scanf("%d", &choice);
switch (choice)
{
case 1:
system("cls");
FCFS(pro, proNum);
choiceMenu();
break;
case 2:
system("cls");
SJF(pro, proNum);
choiceMenu();
break;
case 3:
system("cls");
HPF(pro, proNum);
choiceMenu();
break;
case 4:
system("cls");
RR(pro, proNum);
choiceMenu();
break;
default:
printf("输入错误,请重新尝试\n");
break;
}
} while (choice);
return 0;
}
本次的分享就到此为止了,感谢您的支持,如果您有不同意见,欢迎评论区积极交流
文章浏览阅读1.5w次,点赞10次,收藏129次。文章目录目录模型评估评价指标1.分类评价指标acc、recall、F1、混淆矩阵、分类综合报告1.准确率方式一:accuracy_score方式二:metrics2.召回率3.F1分数4.混淆矩阵5.分类报告6.kappa scoreROC1.ROC计算2.ROC曲线3.具体实例2.回归评价指标3.聚类评价指标1.Adjusted Rand index 调整兰德系数2.Mutual Informa..._model.score
文章浏览阅读344次。因工作需要,在Apache上使用,重新学习配置mod_jk1. 分别安装Apache和Tomcat:2. 编辑httpd-vhosts.conf: LoadModule jk_module modules/mod_jk.so #加载mod_jk模块 JkWorkersFile conf/workers.properties #添加worker信息 JkLogFil_apache mod_jk 虚拟
文章浏览阅读335次。待老夫kotlin大成,扩展:MotionLayout 与 CoordinatorLayout,DrawerLayout,ViewPager 的 交互众所周知,MotionLayout 的 动画是有完成度的 即Progress ,他在0-1之间变化,一.CoordinatorLayout 与AppBarLayout 交互时,其实就是监听 offsetliner 这个 偏移量的变化 同样..._android onoffsetchanged
文章浏览阅读8.3k次,点赞3次,收藏19次。【转】多核处理器的工作原理及优缺点《处理器关于多核概念与区别 多核处理器工作原理及优缺点》原文传送门 摘要:目前关于处理器的单核、双核和多核已经得到了普遍的运用,今天我们主要说说关于多核处理器的一些相关概念,它的工作与那里以及优缺点而展开的分析。1、多核处理器 多核处理器是指在一枚处理器中集成两个或多个完整的计算引擎(内核),此时处理器能支持系统总线上的多个处理器,由总..._多核处理器怎么工作
文章浏览阅读306次。1. eclipse配置lombok 拷贝lombok.jar到eclipse.ini同级文件夹下,编辑eclipse.ini文件,添加: -javaagent:lombok.jar2. myeclipse配置lombok myeclipse像eclipse配置后,定义对象后,直接访问方法,可能会出现飘红的报错。 如果出现报错,可按照以下方式解决。 ..._eclispe每次运行个新项目都需要重新配置lombok吗
文章浏览阅读1.2w次,点赞31次,收藏126次。#注意:笔者在2021/11/11当天调试过这个代码是可用的,由于pdfminer版本的更新,网络上大多数的语法没有更新,我也是找了好久的文章才修正了我的代码,仅供学习参考。1、把pdf文件移动到本代码文件的同一个目录下,笔者是在pycharm里面运行的项目,下图中的x1文件夹存储了我需要转换成文本文件的所有pdf文件。然后要在此目录下创建一个存放转换后的txt文件的文件夹,如图中的txt文件夹。2、编写代码 (1)导入所需库# coding:utf-8import ..._python批量读取文字并批量保存
文章浏览阅读4.3k次。vite在开发阶段采用的是按需加载的方式,不会将所有文件打包。但是生产环境的部署是需要进行打包的,这里它使用的是rollup打包方式。对于代码切割的需求,使用原生动态导入,因此打包后支持新浏览器,对IE的兼容性不是很好,但是可以用对应的polyfill解决。使用esbuild来处理需要pre-undle的在cli.ts的build命令中引入build.ts调用doBuild方法,在这个方法中配置打包参数(input output plugin等)调用buildHtmlPlugin解析文件入口in_vite build
文章浏览阅读1.4k次。http://blog.csdn.net/pipisorry/article/details/52902234Scala 访问修饰符Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。如果没有指定访问修饰符符,默认情况下,Scala对象的访问级别都是 public。Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层_scala ===运算符
文章浏览阅读2.6k次,点赞7次,收藏19次。ER图导出为PDF或图片格式_数据库怎么导出er图
文章浏览阅读655次。CREATE OR REPLACE TRIGGER Trg_ReimFactBEFORE UPDATEON BP_OrderFOR EACH ROWDECLAREPRAGMA AUTONOMOUS_TRANSACTION;--自制事务fc varchar2(255);BEGINIF ( :NEW.orderstate = 2AND :NEW.TransState = 1 ) THENBEG..._oracle触发器更新同一张表
文章浏览阅读513次。目录概念debouncethrottle实现debouncethrottle应用场景debouncethrottle场景举例debouncethrottle概念debounce字面理解是“防抖”,何谓“防抖”,就是连续操作结束后再执行,以网页滚动为例,debounce要等到用户停止滚动后才执行,将连续多次执行合并为一次执行。throttle字面理解是“节流”,何谓“节流”,就是确保一段时..._throttle和debounce应用在哪些场景
文章浏览阅读526次。regex() $regex 正则表达式用于模式匹配,基本上是用于文档中的发现字符串 (下面有例子)注意:若未加 @Field("名称") ,则识别mongdb集合中的key名为实体类属性名。也可以对数组进行索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每一个元素。也可以对整个Document进行索引,排序是预定义的按插入BSON数据的先后升序排列。save: 若新增数据的主键已经存在,则会对当前已经存在的数据进行修改操作。_java 操作mongodb