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;
}