【c++实例总结】 时间time_t转为字符串输出2(std::put_time与std::get_time)

本文深入讲解C++中std::put_time和std::get_time函数的使用,包括它们的内部实现原理,如何进行时间格式化输出和解析输入。通过实例演示如何将tm结构体转换为字符串,以及从字符串中读取时间数据。

1.基础介绍

头文件:

#include <iomanip> //io 操作,manipulator是操作的意思,英文全称的缩写

 

api:

(1)std::put_time

c++源码:

		// TEMPLATE STRUCT _Timeobj
template<class _Elem,
	class _Ptr>
	struct _Timeobj
	{	// store reference to tm object and format
	_Timeobj(_Ptr _Tptr_arg, const _Elem *_Fmt_arg)
		: _Tptr(_Tptr_arg), _Fmtfirst(_Fmt_arg)
		{	// construct from tm pointer and format pointer
		for (_Fmtlast = _Fmtfirst; *_Fmtlast != 0; ++_Fmtlast)
			;	// find end of format string
		}

	_Ptr _Tptr;	// the tm struct pointer
	const _Elem *_Fmtfirst;	// format string start
	const _Elem *_Fmtlast;	// format string end
	};

// TEMPLATE FUNCTION put_time
template<class _Elem> inline
	_Timeobj<_Elem, const struct tm *>
		put_time(const struct tm *_Tptr_arg, const _Elem *_Fmt_arg)
	{	// return a _Timeobj manipulator
	return (_Timeobj<_Elem, const struct tm *>(_Tptr_arg, _Fmt_arg));
	}

template<class _Elem,
	class _Traits,
	class _Elem2> inline
	basic_ostream<_Elem, _Traits>&
		operator<<(basic_ostream<_Elem, _Traits>& _Ostr,
			const _Timeobj<_Elem2, const struct tm *>& _Manip)
	{	// put time information to output stream
	typedef basic_ostream<_Elem, _Traits> _Myos;
	typedef ostreambuf_iterator<_Elem, _Traits> _Iter;
	typedef time_put<_Elem2, _Iter> _Mytput;

	static_assert(is_same<_Elem, _Elem2>::value,
		"wrong character type for put_time");

	ios_base::iostate _State = ios_base::goodbit;
	const typename _Myos::sentry _Ok(_Ostr);

	if (_Ok)
		{	// state okay, insert monetary amount
		const _Mytput& _Tput_fac = _USE(_Ostr.getloc(), _Mytput);
		_TRY_IO_BEGIN
		if (_Tput_fac.put(_Iter(_Ostr.rdbuf()), _Ostr, _Ostr.fill(),
			_Manip._Tptr, _Manip._Fmtfirst, _Manip._Fmtlast).failed())
			_State |= ios_base::badbit;
		_CATCH_IO_(_Ostr)
		}

	_Ostr.setstate(_State);
	return (_Ostr);
	}

由源码可知std::put_time第一个形参是tm,第二个形参是输出格式,返回值是_Timeobj,而c++重载了"<<"支持_Timeobj,所以c++可直接输入类似于std::cout << std::put_time()...这样的操作

 

(2)std::get_time

c++源码:

template<class _Elem,
	class _Ptr>
	struct _Timeobj
	{	// store reference to tm object and format
	_Timeobj(_Ptr _Tptr_arg, const _Elem *_Fmt_arg)
		: _Tptr(_Tptr_arg), _Fmtfirst(_Fmt_arg)
		{	// construct from tm pointer and format pointer
		for (_Fmtlast = _Fmtfirst; *_Fmtlast != 0; ++_Fmtlast)
			;	// find end of format string
		}

	_Ptr _Tptr;	// the tm struct pointer
	const _Elem *_Fmtfirst;	// format string start
	const _Elem *_Fmtlast;	// format string end
	};

		// TEMPLATE FUNCTION get_time
template<class _Elem> inline
	_Timeobj<_Elem, struct tm *>
		get_time(struct tm *_Tptr_arg, const _Elem *_Fmt_arg)
	{	// return a _Timeobj manipulator
	return (_Timeobj<_Elem, struct tm *>(_Tptr_arg, _Fmt_arg));
	}

template<class _Elem,
	class _Traits,
	class _Elem2> inline
	basic_istream<_Elem, _Traits>&
		operator>>(basic_istream<_Elem, _Traits>& _Istr,
			const _Timeobj<_Elem2, struct tm *>& _Manip)
	{	// get time information from input stream
	typedef basic_istream<_Elem, _Traits> _Myis;
	typedef istreambuf_iterator<_Elem, _Traits> _Iter;
	typedef time_get<_Elem2, _Iter> _Mytget;

	static_assert(is_same<_Elem, _Elem2>::value,
		"wrong character type for get_time");

	ios_base::iostate _State = ios_base::goodbit;
	const typename _Myis::sentry _Ok(_Istr);

	if (_Ok)
		{	// state okay, extract time amounts
		const _Mytget& _Tget_fac = _USE(_Istr.getloc(), _Mytget);
		_TRY_IO_BEGIN
		_Tget_fac.get(_Iter(_Istr.rdbuf()), _Iter(0), _Istr, _State,
			_Manip._Tptr, _Manip._Fmtfirst, _Manip._Fmtlast);
		_CATCH_IO_(_Istr)
		}

	_Istr.setstate(_State);
	return (_Istr);
	}

由源码可知std::get_time第一个参数是tm,第二个同样是输入格式,返回值是_Timeobj,而c++也重载了">>"支持_Timeobj,所以

c++可直接输入类似std::cin >> std::get_time()...这样的操作

 

2.例子

#include <iostream>
#include <sstream>
#include <ctime>  //对应c语言time.h
#include <iomanip>//io操作
#include <process.h>

int main()
{
	//显示1例子
	time_t rawtime;
	struct tm info;
	char buffer[80];

	time(&rawtime);

	//localtime_s(&info, &rawtime);  //将time_t转为tm
	//std::localtime非线程安全,使用localtime_r函数代替
	localtime_s(&info, &rawtime);//将time_t转为tm
	
	//ctime是非线程安全的,C标准也建议使用strftime,不要使用ctime、ctime_s
	strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", &info);
	printf("格式化的日期 & 时间 : |%s|\n", buffer);

	//转换例子
	time_t dd = std::mktime(&info);//将tm转为time_t

	//显示2例子:使用std::put_time,std::get_time
	std::cout << std::put_time(&info, "%Y-%m-%d %H:%M:%S");
    //std::cout << std::put_time(&info, "%F %T\n");

	//get_time例子
	std::stringstream ss;
	ss << std::put_time(&info, "%Y-%m-%d %H:%M:%S");

	struct tm info2;
	ss >> std::get_time(&info2, "%Y-%m-%d %H:%M:%S");

	system("pause");
    return 0;
}

注意:

(1)time(null)单位是s

(2)std::put_time、std::get_time中格式与strftime中格式是一致的,格式介绍如下:

strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", &info);

std::cout << std::put_time(&info, "%Y-%m-%d %H:%M:%S");

ss >> std::get_time(&info2, "%Y-%m-%d %H:%M:%S");

=>

%Y-%m-%d %H:%M:%S  

%Y   --年  

%m  --月

%d   --日

%H   --时

%M  --分

%S  --秒

 

更高级:

%F  等价于 %Y-%m-%d,

%T   等价于 %H:%M:%S

所以也可以写为

strftime(buffer, 80, "%F %T", &info);

std::cout << std::put_time(&info, "%F %T");

ss >> std::get_time(&info2, "%F %T");

 

更多格式详细介绍:https://zh.cppreference.com/w/cpp/io/manip/put_time

 

 

 

 

#include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <queue> #include <vector> #include <chrono> #include <atomic> #include <limits> #include <sstream> // 线程状态枚举:等待资源 / 执行操作 enum class ThreadState { WAITING, // 等待缓冲区满/空 WORKING // 执行生产/移动/消费 }; // 全局运行标志 std::atomic<bool> running{ true }; // 全局打印锁(保证日志顺序) std::mutex print_mutex; // 信号量类(支持“带状态追踪”和“纯互斥”两种P操作) class Semaphore { public: Semaphore(int count = 0) : count(count) {} // 【带状态追踪的P操作】用于需要显示“等待/工作”状态的场景(如empty、full信号量) void P(std::atomic<ThreadState>& thread_state, const std::string& thread_name) { // 标记为“等待”并打印日志 thread_state.store(ThreadState::WAITING); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[状态] " << thread_name << " → 等待资源(缓冲区满/空)\n"; } // 实际等待资源 std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [this] { return count > 0; }); --count; // 标记为“工作”并打印日志 thread_state.store(ThreadState::WORKING); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[状态] " << thread_name << " → 开始工作(获取到资源)\n"; } } // 【纯互斥的P操作】用于仅需要互斥、无需状态追踪的场景(如缓冲区内部互斥锁) void P() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [this] { return count > 0; }); --count; } // V操作:释放资源 void V() { std::unique_lock<std::mutex> lock(mtx); ++count; cv.notify_one(); } private: int count; std::mutex mtx; std::condition_variable cv; }; // 缓冲区类(线程安全,支持状态追踪和数据快照) template<typename T> class Buffer { public: Buffer(size_t capacity) : capacity(capacity), empty(capacity), full(0), mutex(1) {} // 写入数据(需传递线程状态和名称,用于追踪“等待/工作”) void put(const T& data, std::atomic<ThreadState>& thread_state, const std::string& thread_name) { empty.P(thread_state, thread_name); // 等待“空位”(带状态追踪) mutex.P(); // 互斥访问(纯互斥,无需状态追踪) queue.push(data); mutex.V(); full.V(); // 通知“有新数据” } // 读取数据(需传递线程状态和名称,用于追踪“等待/工作”) T get(std::atomic<ThreadState>& thread_state, const std::string& thread_name) { full.P(thread_state, thread_name); // 等待“数据”(带状态追踪) mutex.P(); // 互斥访问(纯互斥,无需状态追踪) T data = queue.front(); queue.pop(); mutex.V(); empty.V(); // 通知“有空位” return data; } // 获取缓冲区当前所有数据(快照,纯互斥访问) std::vector<T> get_all_data() { std::vector<T> data_list; mutex.P(); // 纯互斥访问(无需状态追踪) std::queue<T> temp = queue; while (!temp.empty()) { data_list.push_back(temp.front()); temp.pop(); } mutex.V(); return data_list; } size_t get_capacity() const { return capacity; } private: size_t capacity; std::queue<T> queue; // FIFO队列 Semaphore empty; // 控制“空位数量”的信号量(带状态追踪) Semaphore full; // 控制“数据数量”的信号量(带状态追踪) Semaphore mutex; // 纯互斥锁(无需状态追踪) }; // 全局缓冲区实例 Buffer<int> buffer1_1(10); // 一级缓冲区1(容量10) Buffer<int> buffer1_2(10); // 一级缓冲区2(容量10) Buffer<int> buffer2(20); // 二级缓冲区(容量20) // 线程配置参数 struct DelayConfig { unsigned int put_delay = 50; // Put线程延迟(毫秒) unsigned int move_delay = 80; // Move线程延迟(毫秒) unsigned int get_delay = 100; // Get线程延迟(毫秒) unsigned int run_time = 30; // 程序运行时间(秒) }; DelayConfig config; // 输入正整数并校验 unsigned int get_positive_int(const std::string& prompt, unsigned int default_val) { unsigned int val; while (true) { std::cout << prompt << "(默认" << default_val << "): "; if (std::cin >> val) { return val; } else { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cout << "输入错误!请输入正整数。\n"; } } } // 获取用户配置 void get_user_config() { std::cout << "===== 请设置线程参数 =====\n"; config.put_delay = get_positive_int("Put线程延迟(毫秒)", config.put_delay); config.move_delay = get_positive_int("Move线程延迟(毫秒)", config.move_delay); config.get_delay = get_positive_int("Get线程延迟(毫秒)", config.get_delay); config.run_time = get_positive_int("程序运行时间(秒)", config.run_time); std::cout << "==========================\n\n"; } // 数据列表转字符串(格式:[1,2,3]) template<typename T> std::string data_list_to_str(const std::vector<T>& list) { std::stringstream ss; ss << "["; for (size_t i = 0; i < list.size(); ++i) { ss << list[i]; if (i != list.size() - 1) ss << ","; } ss << "]"; return ss.str(); } // 打印缓冲区初始状态 void print_initial_buffers() { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "===== 缓冲区初始状态 =====\n"; std::cout << "buffer1_1(容量" << buffer1_1.get_capacity() << "): " << data_list_to_str(buffer1_1.get_all_data()) << "\n"; std::cout << "buffer1_2(容量" << buffer1_2.get_capacity() << "): " << data_list_to_str(buffer1_2.get_all_data()) << "\n"; std::cout << "buffer2(容量" << buffer2.get_capacity() << "): " << data_list_to_str(buffer2.get_all_data()) << "\n"; std::cout << "==========================\n\n"; } // Put线程:生产数据 → 写入一级缓冲区(含状态追踪) void Put(int buffer_id, int thread_idx) { std::string thread_name = "Put" + std::to_string(buffer_id) + "-" + std::to_string(thread_idx); static std::atomic<int> global_counter{ 0 }; // 全局数据计数器(保证数据唯一) std::atomic<ThreadState> thread_state{ ThreadState::WORKING }; // 线程初始状态为“工作” while (running) { // 原子操作块:生产 + 写入 + 日志(加锁保证日志顺序) std::lock_guard<std::mutex> lock(print_mutex); // 1. 生产数据(当前为“工作”状态) int data = global_counter++; std::cout << "[生产] " << thread_name << " → 生成数据: " << data << "\n"; // 2. 写入对应缓冲区(会触发“等待/工作”状态切换) auto& target_buffer = (buffer_id == 1) ? buffer1_1 : buffer1_2; target_buffer.put(data, thread_state, thread_name); // 3. 打印写入后缓冲区状态(当前为“工作”状态) std::cout << "[写入] " << thread_name << " → buffer1_" << buffer_id << ",数据: " << data << ",当前缓冲区数据: " << data_list_to_str(target_buffer.get_all_data()) << "\n\n"; // 延迟(控制生产速度,保持“工作”状态) std::this_thread::sleep_for(std::chrono::milliseconds(config.put_delay)); } } // Move线程:从一级缓冲区取数据 → 写入二级缓冲区(含状态追踪) void Move(int buffer_id, int thread_idx) { std::string thread_name = "Move" + std::to_string(buffer_id) + "-" + std::to_string(thread_idx); auto& src_buffer = (buffer_id == 1) ? buffer1_1 : buffer1_2; // 源缓冲区 std::atomic<ThreadState> thread_state{ ThreadState::WORKING }; // 线程初始状态为“工作” while (running) { // 1. 从源缓冲区取数据(会触发“等待/工作”状态切换) int data = src_buffer.get(thread_state, thread_name); // 2. 打印“取出后”状态(当前为“工作”状态) { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[取出] " << thread_name << " ← buffer1_" << buffer_id << ",数据: " << data << ",剩余数据: " << data_list_to_str(src_buffer.get_all_data()) << "\n"; } // 3. 写入二级缓冲区(会触发“等待/工作”状态切换) buffer2.put(data, thread_state, thread_name); // 4. 打印“移动后”状态(当前为“工作”状态) { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[移动] " << thread_name << " → buffer2" << ",数据: " << data << ",当前buffer2数据: " << data_list_to_str(buffer2.get_all_data()) << "\n\n"; } // 延迟(控制移动速度,保持“工作”状态) std::this_thread::sleep_for(std::chrono::milliseconds(config.move_delay)); } } // Get线程:从二级缓冲区取数据并消费(含状态追踪) void Get(int thread_idx) { std::string thread_name = "Get-" + std::to_string(thread_idx); std::atomic<ThreadState> thread_state{ ThreadState::WORKING }; // 线程初始状态为“工作” while (running) { // 1. 从二级缓冲区取数据(会触发“等待/工作”状态切换) int data = buffer2.get(thread_state, thread_name); // 2. 打印“消费后”状态(当前为“工作”状态) { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[消费] " << thread_name << " ← buffer2" << ",数据: " << data << ",剩余数据: " << data_list_to_str(buffer2.get_all_data()) << "\n\n"; } // 延迟(控制消费速度,保持“工作”状态) std::this_thread::sleep_for(std::chrono::milliseconds(config.get_delay)); } } int main() { // 1. 获取用户配置 get_user_config(); // 2. 打印缓冲区初始状态 print_initial_buffers(); // 3. 创建线程 std::vector<std::thread> threads; // Put线程:4个操作buffer1_1,4个操作buffer1_2 for (int i = 1; i <= 4; ++i) threads.emplace_back(Put, 1, i); for (int i = 1; i <= 4; ++i) threads.emplace_back(Put, 2, i); // Move线程:1个处理buffer1_1,1个处理buffer1_2 threads.emplace_back(Move, 1, 1); threads.emplace_back(Move, 2, 1); // Get线程:5个消费buffer2数据 for (int i = 1; i <= 5; ++i) threads.emplace_back(Get, i); // 4. 运行指定时间后结束 std::this_thread::sleep_for(std::chrono::seconds(config.run_time)); running = false; // 5. 等待所有线程退出 for (auto& t : threads) { if (t.joinable()) t.join(); } std::cout << "所有线程已结束\n"; return 0; }修改错误
10-16
#include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <queue> #include <vector> #include <chrono> #include <atomic> #include <limits> #include <sstream> #include <conio.h> // Windows下用于无缓冲按键读取(Linux/macOS需替换) // 线程状态枚举:等待资源 / 执行操作 enum class ThreadState { WAITING, WORKING }; // 全局运行标志(控制线程退出) std::atomic<bool> running{ true }; // 全局打印锁(确保日志输出顺序) std::mutex print_mutex; // 信号量类(支持线程状态跟踪) class Semaphore { public: Semaphore(int count = 0) : count(count) {} // P操作:等待资源,同时更新线程状态 void P(std::atomic<ThreadState>& state, const std::string& threadName) { state.store(ThreadState::WAITING); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[状态] " << threadName << " → 等待资源\n"; } std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [this] { return count > 0 || !running; }); if (running) { --count; state.store(ThreadState::WORKING); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[状态] " << threadName << " → 开始工作\n"; } } } // V操作:释放资源 void V() { std::unique_lock<std::mutex> lock(mtx); ++count; cv.notify_one(); } private: int count; std::mutex mtx; std::condition_variable cv; }; // 缓冲区类(线程安全,信号量为public以支持外部唤醒) template <typename T> class Buffer { public: Semaphore empty; // 控制“空位”的信号量(public) Semaphore full; // 控制“数据”的信号量(public) Semaphore mutex; // 控制队列互斥的信号量(public) Buffer(size_t capacity) : empty(capacity), full(0), mutex(1), currentCount(0), totalPut(0), totalGet(0), capacity(capacity) { } // 放入数据(触发状态跟踪) void put(const T& data, std::atomic<ThreadState>& state, const std::string& threadName) { empty.P(state, threadName); mutex.P(state, threadName); queue.push(data); currentCount.fetch_add(1); totalPut.fetch_add(1); mutex.V(); full.V(); } // 取出数据(触发状态跟踪) T get(std::atomic<ThreadState>& state, const std::string& threadName) { full.P(state, threadName); mutex.P(state, threadName); T data = queue.front(); queue.pop(); currentCount.fetch_sub(1); totalGet.fetch_add(1); mutex.V(); empty.V(); return data; } // 统计数据查询接口 size_t getCurrentCount() const { return currentCount.load(); } size_t getTotalPut() const { return totalPut.load(); } size_t getTotalGet() const { return totalGet.load(); } size_t getCapacity() const { return capacity; } // 读取当前所有数据(线程安全快照) std::vector<T> getAllData() const { std::vector<T> dataList; Semaphore tempMutex(1); // 临时互斥锁 tempMutex.P(stateDummy, "Temp"); std::queue<T> temp = queue; while (!temp.empty()) { dataList.push_back(temp.front()); temp.pop(); } tempMutex.V(); return dataList; } private: std::queue<T> queue; std::atomic<size_t> currentCount; std::atomic<size_t> totalPut; std::atomic<size_t> totalGet; size_t capacity; std::atomic<ThreadState> stateDummy{ ThreadState::WORKING }; }; // 线程延迟配置 struct ThreadDelays { unsigned int putDelay = 50; // Put线程延迟(毫秒) unsigned int moveDelay = 80; // Move线程延迟(毫秒) unsigned int getDelay = 100; // Get线程延迟(毫秒) }; ThreadDelays delays; // 输入正整数并校验 unsigned int getPositiveInt(const std::string& prompt, unsigned int defaultVal) { unsigned int val; std::cout << prompt << "(默认" << defaultVal << "): "; while (!(std::cin >> val)) { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cout << "输入错误,请输入正整数: "; } return val; } // 获取线程延迟配置 void getThreadDelays() { std::cout << "===== 设置线程延迟参数 =====\n"; delays.putDelay = getPositiveInt("Put线程延迟(毫秒)", delays.putDelay); delays.moveDelay = getPositiveInt("Move线程延迟(毫秒)", delays.moveDelay); delays.getDelay = getPositiveInt("Get线程延迟(毫秒)", delays.getDelay); std::cout << "============================\n\n"; } // 数据列表转字符串(格式:[1, 2, 3]) template <typename T> std::string dataToString(const std::vector<T>& data) { std::stringstream ss; ss << "["; for (size_t i = 0; i < data.size(); ++i) { ss << data[i]; if (i < data.size() - 1) ss << ", "; } ss << "]"; return ss.str(); } // 打印缓冲区状态(含统计数据) void printBufferStatus(const std::string& name, const Buffer<int>& buffer) { std::lock_guard<std::mutex> lock(print_mutex); std::cout << name << "(容量" << buffer.getCapacity() << "): 当前个数=" << buffer.getCurrentCount() << ", 总放入=" << buffer.getTotalPut() << ", 已取=" << buffer.getTotalGet() << ", 数据=" << dataToString(buffer.getAllData()) << "\n"; } // Put线程:生产并写入一级缓冲区 void putThread(int bufferId, int threadId) { std::string threadName = "Put" + std::to_string(bufferId) + "-" + std::to_string(threadId); std::atomic<ThreadState> state{ ThreadState::WORKING }; static std::atomic<int> dataCounter{ 0 }; Buffer<int>& targetBuffer = (bufferId == 1) ? buffer1_1 : buffer1_2; while (running) { int data = dataCounter++; targetBuffer.put(data, state, threadName); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[生产] " << threadName << " → 数据: " << data << "\n"; std::cout << "[写入] " << threadName << " → buffer1_" << bufferId << "\n"; printBufferStatus("buffer1_" + std::to_string(bufferId), targetBuffer); std::cout << "\n"; } std::this_thread::sleep_for(std::chrono::milliseconds(delays.putDelay)); } } // Move线程:从一级缓冲区取数据并写入二级缓冲区 void moveThread(int bufferId) { std::string threadName = "Move" + std::to_string(bufferId); std::atomic<ThreadState> state{ ThreadState::WORKING }; Buffer<int>& srcBuffer = (bufferId == 1) ? buffer1_1 : buffer1_2; while (running) { int data = srcBuffer.get(state, threadName); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[取出] " << threadName << " ← buffer1_" << bufferId << ", 数据: " << data << "\n"; printBufferStatus("buffer1_" + std::to_string(bufferId), srcBuffer); } buffer2.put(data, state, threadName); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[移动] " << threadName << " → buffer2\n"; printBufferStatus("buffer2", buffer2); std::cout << "\n"; } std::this_thread::sleep_for(std::chrono::milliseconds(delays.moveDelay)); } } // Get线程:从二级缓冲区取数据并消费 void getThread(int threadId) { std::string threadName = "Get-" + std::to_string(threadId); std::atomic<ThreadState> state{ ThreadState::WORKING }; while (running) { int data = buffer2.get(state, threadName); { std::lock_guard<std::mutex> lock(print_mutex); std::cout << "[消费] " << threadName << " ← buffer2, 数据: " << data << "\n"; printBufferStatus("buffer2", buffer2); std::cout << "\n"; } std::this_thread::sleep_for(std::chrono::milliseconds(delays.getDelay)); } } // 全局缓冲区实例 Buffer<int> buffer1_1(10); // 一级缓冲区1(容量10) Buffer<int> buffer1_2(10); // 一级缓冲区2(容量10) Buffer<int> buffer2(20); // 二级缓冲区(容量20) int main() { // 1. 获取线程延迟配置 getThreadDelays(); // 2. 打印初始缓冲区状态 std::cout << "===== 初始缓冲区状态 =====\n"; printBufferStatus("buffer1_1", buffer1_1); printBufferStatus("buffer1_2", buffer1_2); printBufferStatus("buffer2", buffer2); std::cout << "==========================\n\n"; // 3. 创建线程 std::vector<std::thread> threads; // 4个Put线程操作buffer1_1 for (int i = 1; i <= 4; ++i) threads.emplace_back(putThread, 1, i); // 4个Put线程操作buffer1_2 for (int i = 1; i <= 4; ++i) threads.emplace_back(putThread, 2, i); // 2个Move线程分别操作buffer1_1和buffer1_2 threads.emplace_back(moveThread, 1); threads.emplace_back(moveThread, 2); // 5个Get线程操作buffer2 for (int i = 1; i <= 5; ++i) threads.emplace_back(getThread, i); // 4. 记录程序开始时间 auto startTime = std::chrono::steady_clock::now(); // 5. 用户干预:按空格键结束程序 std::cout << "按空格键结束程序...\n"; while (true) { if (_kbhit() && _getch() == ' ') break; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } // 6. 终止程序并唤醒所有等待的线程 running = false; // 主动唤醒所有信号量,确保线程快速退出 buffer1_1.empty.V(); buffer1_1.full.V(); buffer1_1.mutex.V(); buffer1_2.empty.V(); buffer1_2.full.V(); buffer1_2.mutex.V(); buffer2.empty.V(); buffer2.full.V(); buffer2.mutex.V(); // 7. 等待所有线程退出 for (auto& t : threads) { if (t.joinable()) t.join(); } // 8. 计算总运行时间并打印汇总数据 auto endTime = std::chrono::steady_clock::now(); auto totalTime = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count(); std::cout << "\n===== 汇总数据 =====\n"; std::cout << "a) 总的运行时间: " << totalTime << " 秒\n"; std::cout << "b) 每个buffer剩余的数据个数:\n"; std::cout << "buffer1_1: " << buffer1_1.getCurrentCount() << "\n"; std::cout << "buffer1_2: " << buffer1_2.getCurrentCount() << "\n"; std::cout << "buffer2: " << buffer2.getCurrentCount() << "\n"; std::cout << "c) 每个buffer放入数据个数:\n"; std::cout << "buffer1_1: " << buffer1_1.getTotalPut() << "\n"; std::cout << "buffer1_2: " << buffer1_2.getTotalPut() << "\n"; std::cout << "buffer2: " << buffer2.getTotalPut() << "\n"; std::cout << "d) 每个buffer取出的数据个数:\n"; std::cout << "buffer1_1: " << buffer1_1.getTotalGet() << "\n"; std::cout << "buffer1_2: " << buffer1_2.getTotalGet() << "\n"; std::cout << "buffer2: " << buffer2.getTotalGet() << "\n"; return 0; }帮我修改错误
最新发布
10-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kevin--你不知道的事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值