C語(yǔ)言實(shí)現(xiàn)多線程定時(shí)器實(shí)例講解
1. 大致功能介紹
- 實(shí)現(xiàn)任務(wù)列表,定時(shí)器會(huì)間隔一段時(shí)間遍歷列表發(fā)現(xiàn)要執(zhí)行的任務(wù)
- 任務(wù)列表中的所有任務(wù)并行執(zhí)行
- 每個(gè)任務(wù)都可以有自己的定時(shí)器,并且可以選擇是否要重復(fù)執(zhí)行
- 定義方便的任務(wù)函數(shù)實(shí)現(xiàn)接口
- 定時(shí)器可以由用戶自定義何時(shí)啟動(dòng)和停止
- 提供等待功能,保證任務(wù)列表中的所有任務(wù)執(zhí)行完成
- 提供任務(wù)列表的傳參功能
2. API庫(kù)介紹
void setTick(int val);
設(shè)置定時(shí)間的間隔時(shí)間tick,若設(shè)置tick為1000,且任務(wù)的定時(shí)器時(shí)間為1000,則任務(wù)會(huì)在1秒后執(zhí)行,默認(rèn)tick為1秒,最小tick時(shí)間為1us。
void addTimerTask(TimerTask task, int val, int autoreset, void *arg);
向任務(wù)列表注冊(cè)一個(gè)任務(wù),并指定其定時(shí)時(shí)間val,以及是否要重復(fù)執(zhí)行autoreset,并可以指定參數(shù)的地址。
task需要按照頭文件提供的宏來(lái)編寫(xiě),例如:
TASK_START(test2, arg)
//body
Arg *temp = (Arg*)arg;
temp->ret = temp->a + temp->b;
printf("This is a test2\n");
TASK_END
TASK_START(name, arg)是任務(wù)頭,name是任務(wù)名,arg是參數(shù)地址,TASK_END是任務(wù)結(jié)尾。任務(wù)體內(nèi)可編寫(xiě)正常的c語(yǔ)言代碼,并使用參數(shù)arg指針。
autoreset有兩個(gè)可選項(xiàng):AUTORESET(重復(fù)執(zhí)行),NORESET(執(zhí)行一次)。
若沒(méi)有參數(shù),可將arg參數(shù)設(shè)置為NULL。
void TimerWait();
用于等待任務(wù)列表中所有任務(wù)執(zhí)行完畢。
void TimerStop();
用于停止定時(shí)器。
void StartTimer();
用于啟動(dòng)定時(shí)器。
3. 一個(gè)例子
#include <stdio.h>
#include "timer.h"
typedef struct Argument{
int a;
int b;
int ret;
}Arg;
//任務(wù)1,打印語(yǔ)句
TASK_START(test1, arg)
printf("This is a test1\n");
TASK_END
//任務(wù)2,計(jì)算arg中兩個(gè)數(shù)的和,打印語(yǔ)句
TASK_START(test2, arg)
Arg *temp = (Arg*)arg;
temp->ret = temp->a + temp->b;
printf("This is a test2\n");
TASK_END
//任務(wù)3,打印語(yǔ)句
TASK_START(test3, arg)
printf("This is a test3\n");
TASK_END
void main(){
Arg arg;
//設(shè)置tick 為 500ms
setTick(500 * 1000);
//添加任務(wù)1到任務(wù)列表,設(shè)置定時(shí)器時(shí)間為2.5s,重復(fù)執(zhí)行,無(wú)參數(shù)
addTimerTask(test1, 5, AUTORESET, NULL);
arg.a = 2; arg.b = 3;
//添加任務(wù)2到任務(wù)列表,設(shè)置定時(shí)器時(shí)間為0.5s,不重復(fù)執(zhí)行,參數(shù)為arg
addTimerTask(test2, 1, NORESET, &arg);
//添加任務(wù)3到任務(wù)列表,設(shè)置定時(shí)器時(shí)間為1s,重復(fù)執(zhí)行,無(wú)參數(shù)
addTimerTask(test3, 2, AUTORESET, NULL);
//啟動(dòng)定時(shí)器
StartTimer();
printf("Timer is started\n");
//程序等待5秒
sleep(5);
//停止定時(shí)器
TimerStop();
//等待所有任務(wù)執(zhí)行完畢
TimerWait();
//打印任務(wù)二的計(jì)算結(jié)果
printf("%d\n", arg.ret);
}
運(yùn)行結(jié)果:

4. 庫(kù)文件源碼
timer.h:
#ifndef TIMER_H
#define TIMER_H
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#define AUTORESET 1
#define NORESET 0
#define TASK_START(name, arg) void* name(void *arg){
#define TASK_END return NULL;}
typedef void* (*TimerTask)(void* arg);
struct TaskItem{
TimerTask task;
int init_counter;
int counter;
pthread_t th;
void *arg;
void *ret;
int flag;
int autoreset;
struct TaskItem *next;
};
void setTick(int val);
void* EventLoop(void* arg);
void addTimerTask(TimerTask task, int val, int autoreset, void *arg);
void TimerWait();
void TimerStop();
void StartTimer();
#endif //TIMER_H
timer.cpp
#include "timer.h"
#define STOPFLAG 0
#define RUNFLAG 1
static int tick = 1000 * 1000;
static struct TaskItem head = {
.next = NULL,
};
static pthread_t loop_thread;
static int flag = STOPFLAG;
static int tasknum = 0;
void setTick(int val){
tick = val;
}
void* EventLoop(void* arg){
struct TaskItem *task = head.next;
struct TaskItem *pretask = &head;
while(flag == RUNFLAG && tasknum > 0){
while(task != NULL){
if(task->counter == 0){ // it is time for doing task
if(task->flag == STOPFLAG){ // task is not created
if(0 != pthread_create(&(task->th), NULL, task->task, task->arg)){ // do a task
printf("Failed to create user's task");
}
else{
task->flag = RUNFLAG;
}
}
else{
if(0 != pthread_kill(task->th, 0)){ // current task is completed
if(task->autoreset == AUTORESET){ // repeat execute
task->counter = task->init_counter;
task->flag = STOPFLAG;
}
else{ // delete a task
pretask->next = task->next;
free(task);
task = pretask->next;
tasknum--;
continue;
}
}
}
}
else{
task->counter--;
}
pretask = pretask->next;
task = task->next;
}
usleep(tick); // sleep a tick
task = head.next;
pretask = &head;
}
flag = STOPFLAG;
}
void addTimerTask(TimerTask task, int val, int autoreset, void *arg){
struct TaskItem *node;
node = (struct TaskItem*)malloc(sizeof(struct TaskItem));
node->next = head.next;
head.next = node;
node->arg = arg;
node->counter = val;
node->init_counter = val;
node->task = task;
node->flag = STOPFLAG;
node->autoreset = autoreset;
tasknum++;
}
void TimerWait(){
pthread_join(loop_thread, NULL);
}
void TimerStop(){
flag = STOPFLAG;
}
void StartTimer(){
flag = RUNFLAG;
if(0 != pthread_create(&loop_thread, NULL, EventLoop, NULL)){
printf("Failed to create loop task.\n");
}
}
注意事項(xiàng)
- 編譯要加 -l pthread選項(xiàng)
- 庫(kù)實(shí)現(xiàn)在Linux環(huán)境,如果是windows需要修改線程創(chuàng)建函數(shù),休眠函數(shù)以及相應(yīng)的頭文件。
到此這篇關(guān)于C語(yǔ)言實(shí)現(xiàn)多線程定時(shí)器實(shí)例講解的文章就介紹到這了,更多相關(guān)C語(yǔ)言如何實(shí)現(xiàn)多線程定時(shí)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C 語(yǔ)言基礎(chǔ)之C 語(yǔ)言三大語(yǔ)句注意事項(xiàng)
今天講解的內(nèi)容,則是自己對(duì)于這三種語(yǔ)句一些細(xì)節(jié)的簡(jiǎn)單介紹,分支語(yǔ)句:if,switch、循環(huán)語(yǔ)句:while,for,do while、goto語(yǔ)句,感興趣的小伙伴可以參考下面具體的文章內(nèi)容2021-09-09
C++使用GDAL庫(kù)實(shí)現(xiàn)Tiff文件的讀取
這篇文章主要為大家詳細(xì)介紹了C++使用GDAL庫(kù)實(shí)現(xiàn)Tiff文件的讀取的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03
C++實(shí)現(xiàn)LeetCode(347.前K個(gè)高頻元素)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(347.前K個(gè)高頻元素),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
基于Matlab實(shí)現(xiàn)野狗優(yōu)化算法的示例代碼
野狗優(yōu)化算法(Dingo?Optimization?Algorithm,?DOA)模仿澳大利亞野狗的社交行為。DOA算法的靈感來(lái)源于野狗的狩獵策略,即迫害攻擊、分組策略和食腐行為。本文將通過(guò)Matlab實(shí)現(xiàn)這一算法,感興趣的可以了解一下2022-04-04
C語(yǔ)言中進(jìn)程信號(hào)集的相關(guān)操作函數(shù)詳解
這篇文章主要介紹了C語(yǔ)言中進(jìn)程信號(hào)集的相關(guān)操作函數(shù)詳解,包括sigismember函數(shù)和sigfillset函數(shù)以及sigemptyset函數(shù)的用法,需要的朋友可以參考下2015-09-09
C++中將Char轉(zhuǎn)換成String的4種方法
本文主要介紹了C++中將Char轉(zhuǎn)換成String的4種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03

