2_6_12 recursive_mutex、timed_mutex、recursive_timed_mutex、随机数、系统时间、线程池

6_12_recursive_timed_mutex.cpp

#include <hjcommon.hpp>
#include <list>
#include <mutex>

using namespace std;
HJ_NS_USING

class D
{
public:
	void write()
	{
		for(int i=0; i<100000; ++i)
		{
			std::unique_lock<recursive_timed_mutex> uniqueLock(m_mutex); // 由于使用的 recursive_timed_mutex ,这里不会造成死锁。
//			if (m_mutex.try_lock_for(100ms)) // 100毫秒内如果拿到了锁,返回true,否则false
			if (m_mutex.try_lock_until(std::chrono::steady_clock::now() + 100ms)) // 等待至当前时间后的100毫秒,期间内如果拿到了锁,返回true,否则false
			{
				cout << "write : " << i << endl;
				m_list.push_back(i);
				m_mutex.unlock(); // 记得解锁
			}
			else cout << "没拿到锁." << endl;
		}

		std::unique_lock<recursive_timed_mutex> uniqueLock(m_mutex);
		isWriteFinish = true;
	}
	void read()
	{
		while(true)
		{
			std::unique_lock<recursive_timed_mutex> uniqueLock(m_mutex);
			if (!m_list.empty())
			{
				int var = m_list.front();
				m_list.pop_front();
				cout << "read : " << var << endl;
			}
			else
			{
				if (isWriteFinish) break;
				sleep(5us);
			}
		}
	}

private:
	bool isWriteFinish = false;
	std::list<int> m_list;
//	std::recursive_mutex m_mutex; // 可以
//	std::timed_mutex m_mutex; // 可以
	std::recursive_timed_mutex m_mutex; // 可以
};

int main_2_6_12(int argc, char *argv[])
{
	// std::chrono::steady_clock::now() 获取当前tick值,中途修改系统时间,是无法改变tick值的,用此算法可精确获取时间过去了多久
//	std::chrono::steady_clock::time_point startPoint = std::chrono::steady_clock::now();
	auto startTime = getTimePoint(); // 计算耗时

	D a;
	thread writeThread(&D::write, &a);
	thread readThread(&D::read, &a);
	writeThread.join();
	readThread.join();

	// c++11 中其他的锁:
	// recursive_mutex 递归的独占互斥量,重复加锁不会造成卡死,慎用
	// timed_mutex 带超时功能的独占互斥量
		// try_lock_for() 相比std::mutex 多了这两个函数
		// try_lock_unitil()
	// recursive_timed_mutex 带超时功能的递归独占互斥量,慎用

	// 计算耗时
	/*
			system_clock:系统时钟,提供了to_time_t()、from_time_t()接口来将timepoint和c系统时间time_t做转换。
			steady_clock:不变时钟,并不是使用物理时间的增长来描述的,而是以一个固定的比率来增长。
			high_resolution_clock:高精度时钟。
	 */
//	std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
//	std::chrono::duration<double> timeFly = std::chrono::duration_cast<std::chrono::duration<double>>(end - start); // 将tick值转换为秒
//	cout << "took time=" << timeFly.count() << " seconds." << endl; // timeFly.count() 计算耗时,单位秒
	cout << "took time=" << calcTimeCounts(startTime) << " seconds." << endl; // took time=1.16168 seconds.
	cout << "end." << endl;
	return 0;
}

6_13_随机数_系统时间.cpp

#include "hjcommon.hpp"
#include <random> // C++98
#include <sys/timeb.h>
#include <iomanip>

// 获取时间戳(秒)
static long getSecondTimestamp()
{
	time_t tDate;
	time(&tDate);
	return tDate;
}
// 获取时间戳(毫秒)
static long getMilliTimestamp() // 需要 #include <sys/timeb.h>
{
	struct timeb t;
	ftime(&t); // ftime(&timeb) 获取精确到毫秒的时间戳 , time(&time_t);获取的时间戳只精确到秒
	return 1000 * t.time + t.millitm; // t.time 的时间戳只精确到秒, t.millitm 为毫秒段的值
}
// 获取时间戳(毫秒) c++98
static long getMilliTimestamp_cpp() // 需要 #include <sys/timeb.h>
{
	std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); // system_clock 表示系统时间
	// time_since_epoch() 函数作用 : 用于获取当前时间点距离时间戳的时间长度
	std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
	return ms.count(); // 因为用的是 chrono::milliseconds ,所以 count() 返回毫秒
}
// 获取系统时间,标准格式 2019-02-02 17:04:27
static String getStandardTime()
{
	time_t tDate;
	time(&tDate); // 获取系统当前时间戳(只精确到秒)
	struct tm *now = localtime(&tDate); // 将time_t转化为struct tm结构
	int year = now->tm_year + 1900; // 从1900年开始的
	int mon = now->tm_mon + 1; // 月份从0开始
	int day = now->tm_mday;
	int hour = now->tm_hour;
	int min = now->tm_min;
	int sec = now->tm_sec;
	char buf[128];
//	strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", now); // 使用 strftime 函数转换为时间格式的字符串
	sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); // 手动写。
	return String(buf);
}
// 将时间戳(秒)转换为标准格式时间 2019-02-02 17:04:27
static String timestamp_to_stardardtime(long timestamp)
{
	time_t tick = timestamp;
	char buf[100];

	struct tm *tm = localtime(&tick);
	strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); // strftime 函数将时间格式化

	return String(buf);
}
// 标准格式时间转换为时间戳,秒
static long standardtime_to_timestamp(const String &time)
{
	struct tm stm;
	int iY, iM, iD, iH, iMin, iS;
	const char *standardtime = time.c_str(); // 标准时间格式 : 2019-02-02 17:04:27

	memset(&stm, 0, sizeof(stm));
	iY = atoi(standardtime); // atoi() 将字符串中的数字转换为int,若字符串中有非数字,那么字符读取到该位置
	iM = atoi(standardtime+5); // 指针向后偏移5,下 类同
	iD = atoi(standardtime+8);
	iH = atoi(standardtime+11);
	iMin = atoi(standardtime+14);
	iS = atoi(standardtime+17);

	stm.tm_year=iY-1900;
	stm.tm_mon=iM-1;
	stm.tm_mday=iD;
	stm.tm_hour=iH;
	stm.tm_min=iMin;
	stm.tm_sec=iS;

	return mktime(&stm);
}

int main_2_6_13_1(int argc, char *argv[])
{
	// 整型随机数 C++98
//	std::default_random_engine engine(std::random_device()()); // 通过operator()取得设备产生的随机值
	std::default_random_engine engine; // 若使用默认的种子,产生的随机数是不变的
	engine.seed(std::random_device()()); // 可以,同构造时传一样
	std::uniform_int_distribution<int> distr1(-10, 10); // [-10,10] 包含-10、10 ,uniform_int_distribution对应int类型,等概率
	for (int i = 0; i < 5 ; ++i)
	{
		cout << distr1(engine) << endl; // distr1(engine) 产生随机数
	}
	cout << "--------------------------------" << endl;
	// 小数随机数
	std::uniform_real_distribution<double> distr2(-1, 1); // -1到1间小数,包含-1、1 ,uniform_real_distribution对应double类型,等概率
	for (int i = 0; i < 5; ++i)
	{
		cout << distr2(engine) << endl;
	}
	cout << "--------------------------------" << endl;

	// 获取系统时间,秒
	String standardTime = getStandardTime();
	cout << "本地时间 : " << standardTime << endl; // 本地时间 : 2019-02-02 17:04:27
	// 获取系统时间戳
	cout << "本地时间戳(秒) : " << setw(21) << getSecondTimestamp() << endl;
	cout << "本地时间戳(毫秒) : " << setw(22) << getMilliTimestamp() << endl;
	cout << "本地时间戳(毫秒) c++98 : "  << setw(16) << getMilliTimestamp_cpp() << endl;
	long timestamp = standardtime_to_timestamp(standardTime);
	cout << "标准格式时间 to timestamp : " << timestamp << endl;
	standardTime = timestamp_to_stardardtime(timestamp);
	cout << "timestamp to 标准格式时间 : " << standardTime << endl; // 本地时间 : 2019-02-02 17:04:27

	return 0;
}

6_13_线程池.cpp

#include "hjcommon.hpp"

int main(int argc, char *argv[])
{
	// 虚假唤醒
	// 线程池 : 当系统开销很大的时候,这时创建线程是可能会失败的,这就给程序带来了稳定性的问题,用线程池来处理。
	// 线程数量,建议 200 个内,不要超过 500 个

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值