效果图:
- 当打印任务中出现优先级高的任务则先打印
- 当打印任务的份数超过最大容量时还能记忆已打印份数
- 当打印队列的任务数不超过最大容量时
- 当打印任务还没全部打印完时出现比它优先级更高的任务
- 当打印任务优先级相同时优先打印内容少的
#include<stdio.h>
#include<iostream>
#include<queue>
#include<Windows.h>
#include<string>
#include<time.h>
using namespace std;
int error = 0;
int cnt = 0;//用来记录总任务数
int n;//用来记录当次输入的任务数量
int cur = 0;
int pre = 0;
CRITICAL_SECTION Printer; //定义Printer临界区资源变量
#define MAXSIZE 2 //打印队列的最大长度
struct Job {
int id;//任务的序号
int level;//任务的优先级
int capacity;//打印内容的大小
int amount = 0;
string print_work;
};//任务结构体的创建
priority_queue<Job> work, q;
Job job[100000];
int done[100000];
DWORD thread_1, thread_2;
HANDLE hThread_1, hThread_2;
bool operator<(const Job& s1, const Job& s2) {
if (s1.level == s2.level)//优先度相同返回打印内容少的
return s1.capacity> s2.capacity;
return s1.level < s2.level;//返回优先度高的任务
}
void lock()
{
EnterCriticalSection(&Printer);
}
void unlock()
{
LeaveCriticalSection(&Printer);
}
DWORD CALLBACK work_add(LPVOID param)
{
while (!error)
{
lock();//work_add线程占用临界区资源
{
cout << "请输入需要添加的打印任务个数(输入0则打印完剩下任务)";
cin >> n;
cur =cur+n-pre;
if (n == 0) //不再有新的打印任务
{
unlock();//停止占用临界区资源
while (!work.empty())
Sleep(0);//如果打印队列中还有剩余的任务,则令work_print线程打印完所有剩余的任务
error = 1;//跳出循环
break;
}
for (int i = cnt; i < n + cnt; i++)
{
string st;
job[i].id = i + 1;
cout << "请输入第" << i + 1 << "个任务的优先级、打印份数、打印内容:";
cin >> job[i].level >> job[i].amount;
if (job[i].level > 7)
job[i].level = 7;
getline(cin, st);//预防打印内容带有空格cin无法接收的情况
job[i].print_work = st;
job[i].capacity = job[i].print_work.size();//打印内容的大小
}
for (int i = cnt; i < n + cnt; i++)
{
cur+= job[i].amount-1;
for (int j = 1; j <= job[i].amount; j++)
{
q.push(job[i]);//将job的任务插入临时队列
}
}
if (work.size()>0)
{
while (!work.empty())
{
q.push(work.top());
work.pop();
}
}
for (int i = 0; i < cur; i++) {
if (work.size() == MAXSIZE) {//如果work打印队列满了
unlock();//停止占用临界区资源
while (work.size() == MAXSIZE)
Sleep(0);//让其他线程运行
lock();//再次占用临界区资源
}
work.push(q.top());//打印任务入队
int x = q.top().id;
q.pop();
cout << "作业序号" << x << "进入打印队列准备打印" << endl;
}
cnt += n;//记录总任务数
}
unlock();//停止占用临界区资源
}
return 0;
}
DWORD CALLBACK work_print(LPVOID param)
{
while (!error)
{
lock();//work_print线程占用临界区资源
{
cout <<endl<< "开始打印........" << endl;
while (!work.empty()) {//将当前work打印任务队列中所有任务打印完成
auto t1 = clock();
cout << "任务序号" << work.top().id << " 正在打印...";
cout << '[';
for (int i = 0; i < 100; i += 10)
{
Sleep(work.top().capacity * 25);
cout << (char)0xa8 << (char)0x80;
}
auto t2 = clock();
cout << "] 100%" << " 打印耗时:"<<(t2 - t1)/1000<<"s"<< endl;
cout << "第"<<done[work.top().id]+1<< "份 "<< "任务序号" << work.top().id << " 打印完成:" << work.top().print_work << endl;
done[work.top().id]++;
work.pop();
pre++;
}
}
cout << "打印结束........" << endl << endl;
unlock();
while (work.empty())
Sleep(0);
}
return 0;
}
void CreatePrinterThread()
{
hThread_1 = CreateThread(NULL, 0, work_add, NULL, 0, &thread_1);
if (hThread_1 == NULL)
{
cout << "线程创建失败..." << endl;
error = 1;
exit(error);
}
hThread_2 = CreateThread(NULL, 0, work_print, NULL, 0, &thread_2);
if (hThread_2 == NULL)
{
cout << "线程创建失败..." << endl;
error = 1;
exit(error);
}
}
int main()
{
cout << "--------------------------欢迎使用打印机--------------------------" << endl;
cout << " 注意事项:打印队列最大容量为:" << MAXSIZE << " 任务优先级为:1-7(数字越大越紧急)" << endl << endl;
InitializeCriticalSection(&Printer);//初始化打印机临界区资源
CreatePrinterThread();//开始创建添加任务、打印任务两条线程
while (!error)
Sleep(0);
system("pause");
cout << "--------------------------打印机已退出--------------------------" << endl;
DeleteCriticalSection(&Printer);//摧毁打印机临界区资源
return 0;
}