前言
在我们平时控制台程序的编写过程中,使用多线程, 如: 子线程中执行任务, 主线程线程中检测用户输入, 然后根据用户输入, 来控制工作线程状态;
如果仅仅是快速做测试, 可以使用C语言中的kbhit()和getch()来实现上述功能.
个人理解: kbhit()内部也是封装了一个线程来检测用户键盘输入.
本示例使用标志位 flag
控制另一个线程的停止。
示例:
#include <iostream>
#include <thread>
#include <Windows.h>
#include <conio.h> // _kbhit(), _getch()
using namespace std;
extern int flag = 1;
void rec_cmd() {
int counter = 0;
char exitflag = '\0';
while (1)
{
Sleep(50);
//函数名:kbhit()
//功能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
if (_kbhit())
{
// 函数名: getch()
// 功能及返回值: 从键盘上读取到的字符
exitflag = _getch();
if (exitflag == 'q' || exitflag == 'Q')
{
std::cout << "用户输入:" << exitflag << ", 退出循环\n";
flag = 0;
break;
}
}
}
std::cout << "已经退出了循环\n";
}
void print_test() {
while (flag) {
Sleep(1000);
cout << "print test is ok ."<<endl;
}
}
int main()
{
thread t1(rec_cmd);
thread t2(print_test);
t1.join();
t2.join();
return 0;
}
控制台输出
另附用 c11 封装的线程安全队列
#pragma once
#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <queue>
template <class T>
class Queue {
protected:
// Data
std::queue<T> _queue;
typename std::queue<T>::size_type _size_max;
// Thread gubbins
std::mutex _mutex;
std::condition_variable _fullQue;
std::condition_variable _empty;
// Exit
// 原子操作
std::atomic_bool _quit; //{ false };
std::atomic_bool _finished; // { false };
public:
Queue(const size_t size_max) :_size_max(size_max) {
_quit = ATOMIC_VAR_INIT(false);
_finished = ATOMIC_VAR_INIT(false);
}
bool push(T& data)
{
std::unique_lock<std::mutex> lock(_mutex);
while (!_quit && !_finished)
{
if (_queue.size() < _size_max)
{
_queue.push(std::move(data));
//_queue.push(data);
_empty.notify_all();
return true;
}
else
{
// wait的时候自动释放锁,如果wait到了会获取锁
_fullQue.wait(lock);
}
}
return false;
}
bool pop(T &data)
{
std::unique_lock<std::mutex> lock(_mutex);
while (!_quit)
{
if (!_queue.empty())
{
//data = std::move(_queue.front());
data = _queue.front();
_queue.pop();
_fullQue.notify_all();
return true;
}
else if (_queue.empty() && _finished)
{
return false;
}
else
{
_empty.wait(lock);
}
}
return false;
}
// The queue has finished accepting input
void finished()
{
_finished = true;
_empty.notify_all();
}
void quit()
{
_quit = true;
_empty.notify_all();
_fullQue.notify_all();
}
int length()
{
return static_cast<int>(_queue.size());
}
};
小白 如有错误,欢迎提出,谢谢!
另附多线程学习资料:秒杀多线程第一篇 多线程笔试面试题汇总 - MoreWindows Blog - CSDN博客
参考文献:
1.使用kbhit()和getch()无阻塞接收用户键盘输入 - liuhhaiffeng的专栏 - CSDN博客
2.基于std::queue C++11 线程安全队列。 - fengchu3415的博客 - CSDN博客