手写线程池

简单介绍

我们写的线程池中预计最多会有8个线程在同时工作。
这8个线程会组成一个工作队列(队列使用双向链表进行实现)。
需要我们去处理的任务量暂定为2000条。
这2000条任务会依次存储到一个任务队列中(队列使用双向链表进行实现)。
工作内容为将自身的ID给输出到屏幕上。
每个线程会先判断任务队列中有没有任务需要去处理,如果有的话就去调用任务函数去处理任务
任务全部处理完成后将相关的资源进行释放

代码

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define COUNT_TASKS 2000
#define COUNT_WORKERS 1

//双向链表的插入,头插法
#define LIST_INSERT(item,list) do \
{                                 \
    if (list == NULL){            \
        list = item;              \
        list->next = NULL;        \
        list->pre = NULL;         \
    }                             \
    else{                         \
        item->next = list;        \
        list->pre = item;         \
        list = item;              \
        list->pre = NULL;         \
    }                             \
} while (0);                      

//双向链表 删除头节点
#define LIST_REMOVE(list) do     \
{                                \
    if(list == NULL);            \
    else{                        \
        list = list->next;       \
        if(list != NULL)         \
        list ->pre = NULL;       \
    }                            \
} while (0);                     


//任务队列中的任务函数
void function_task(int id){
    printf("The id of task is %d\n",id);
}
//任务队列
struct Task
{
    //ID
    int id;
    //前驱节点
    struct Task *pre;  
    //后继节点
    struct Task *next;
    //任务函数
    void (*function_task)(int id);
};

//工作队列
struct Work
{
    //进程ID
    pthread_t thread_id;
    //前驱节点
    struct Work *pre;
    //后继
    struct Work *next;
    //进程结束标志 0位正常 1为结束
    int terminal_tag;
};

//线程池
struct  ThreadPool
{
    //工作队列
    struct Work *works;
    //任务队列
    struct Task *tasks;
    //互斥锁
    pthread_mutex_t mutex;
    //条件变量
    pthread_cond_t cond;
};

//每个线程的回调函数
void *call_back(void *arg){
    struct ThreadPool *thread_pool = (struct ThreadPool *)arg;
    while (1)
    {
        //上锁
        int res = pthread_mutex_lock(&thread_pool->mutex);
        if (res)
        {
            perror("pthread_mutex_lock\n");
        }

        //debug
        // if (thread_pool->tasks == NULL)
        // {
        //     printf("wait before\n");
        // }

        while(thread_pool->tasks == NULL)
        {
            int res = pthread_cond_wait(&thread_pool->cond,&thread_pool->mutex);
            // printf("%d\n",res);
            if (res)
            {
                perror("pthread_mutex_lock\n");
            }
            if (thread_pool->works->terminal_tag == 1)
            break;
        }

        if (thread_pool->works->terminal_tag == 1)
        break; 

        //debug
        // if (thread_pool->tasks == NULL)
        // {
        //     printf("remove before\n");
        // }

        //任务队列不为空
        struct Task *task = thread_pool->tasks;
        LIST_REMOVE(thread_pool->tasks);

        //debug
        // if (thread_pool->tasks == NULL)
        // {
        //     printf("over\n");
        // }
        
        //执行任务
        task->function_task(task->id);
        // printf("helloha\n");

        //解锁
        res = pthread_mutex_unlock(&thread_pool->mutex);
        if (res)
        {
            perror("pthread_mutex_lock\n");
        }

        free(task);
    }
}

//推送任务
int task_push(struct Task *task,struct ThreadPool *thread_pool){
    //上锁
    int res = pthread_mutex_lock(&thread_pool->mutex);
    if (res)
    {
        perror("pthread_mutex_lock\n");
        return -1;
    }
    // printf("hello\n");
    LIST_INSERT(task,thread_pool->tasks);
    // printf("hello\n");
    pthread_cond_signal(&thread_pool->cond);
    //解锁
    res = pthread_mutex_unlock(&thread_pool->mutex);
    if (res)
    {
        perror("pthread_mutex_unlock\n");
        return -2;
    }
    //   printf("hello\n");

    return 0;
}

//线程池初始化
int thread_pool_initial(struct ThreadPool *thread_pool){

    int res = pthread_mutex_init(&thread_pool->mutex,NULL);
    if (res)
    {
        perror("pthread_mutex_init\n");
        return -1;
    }
    res = pthread_cond_init(&thread_pool->cond,NULL);
    if (res)
    {
        perror("pthread_cond_init\n");
        return -2;
    }

    thread_pool->tasks = NULL;
    thread_pool->works = NULL;

    for (int i = 0; i < COUNT_WORKERS; i++)
    {
        struct Work *work = (struct Work*)malloc(sizeof(struct Work));
        work->terminal_tag = 0;
        res = pthread_create(&work->thread_id,NULL,call_back,thread_pool);
        if (res)
        {
            perror("pthread_creat\n");
            return -2;
        }
        
        LIST_INSERT(work,thread_pool->works);
    }

    for (int i = 1; i <= COUNT_TASKS; i++)
    {
        // printf("%d\n",i);
        struct Task *task = (struct Task*)malloc(sizeof(struct Task));
        if (task == NULL)
        {
            perror("malloc\n");
            return -1;
        }
        task->id = i;
        task->function_task = function_task;
        task_push(task,thread_pool);
        
        // printf("%d\n",i);
    }

    return 0;
}

int thread_pool_destroy(struct ThreadPool *thread_pool){
    struct Work *work = (struct Work*)malloc(sizeof(struct Work));
    while (1)
    {
        //上锁
        int res = pthread_mutex_lock(&thread_pool->mutex);
        if (res)
        {
            perror("pthread_mutex_lock\n");
            return -1;
        }

        if (thread_pool->tasks == NULL)
        {
            for (int i = 0; i < COUNT_WORKERS; i++)
            {
                work = thread_pool->works;
                work->terminal_tag = 1;
                work = work->next;
            }
            res = pthread_cond_broadcast(&thread_pool->cond);
            if (res)
            {
                perror("pthread_cond\n");
                return -2;
            }
             //解锁
            res = pthread_mutex_unlock(&thread_pool->mutex);
            break;
        }

        //解锁
        res = pthread_mutex_unlock(&thread_pool->mutex);
        if (res)
        {
            perror("pthread_mutex_lock\n");
            return -2;
        }
    }
        //等待线程结束
        for (int i = 0; i < COUNT_WORKERS; i++)
        {
            work = thread_pool->works;
            if(pthread_join(work->thread_id,NULL))
            printf("pthread_join error\n");
            LIST_REMOVE(thread_pool->works);
            free(work);
        }
    

    return 0;
}


int main(){
    struct ThreadPool *thread_pool = (struct ThreadPool*)malloc(sizeof(struct ThreadPool));
    thread_pool_initial(thread_pool);
    thread_pool_destroy(thread_pool);
    // getchar();
    return 0;
}

代码运行结果

在这里插入图片描述

如果代码或者文章中有什么错误,欢迎指出。

手写一个简单的线程池,你可以按照以下步骤进行: 1. 创建一个任务队列,用于存储待执行的任务。 2. 创建一个固定数量的线程池,用于执行任务。 3. 每当有任务提交到线程池时,将任务添加到任务队列中。 4. 线程池中的每个线程会不断从任务队列中获取任务并执行。 5. 执行完一个任务后,线程继续从任务队列中获取下一个任务,并重复执行,直到任务队列为空。 下面是一个简单的 Java 代码示例: ```java import java.util.LinkedList; import java.util.Queue; public class ThreadPool { private final int poolSize; private final WorkerThread[] workerThreads; private final Queue<Runnable> taskQueue; public ThreadPool(int poolSize) { this.poolSize = poolSize; this.taskQueue = new LinkedList<>(); this.workerThreads = new WorkerThread[poolSize]; for (int i = 0; i < poolSize; i++) { workerThreads[i] = new WorkerThread(); workerThreads[i].start(); } } public void submit(Runnable task) { synchronized (taskQueue) { taskQueue.add(task); taskQueue.notify(); // 唤醒等待的线程 } } private class WorkerThread extends Thread { @Override public void run() { while (true) { Runnable task; synchronized (taskQueue) { while (taskQueue.isEmpty()) { try { taskQueue.wait(); // 等待新任务的到来 } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } task = taskQueue.poll(); } try { task.run(); // 执行任务 } catch (RuntimeException e) { // 异常处理 } } } } // 使用示例 public static void main(String[] args) { ThreadPool threadPool = new ThreadPool(5); for (int i = 0; i < 10; i++) { final int index = i; threadPool.submit(() -> { System.out.println("Task " + index + " is running."); try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("Task " + index + " is complete."); }); } } } ``` 上述代码中,首先创建了一个任务队列 `taskQueue`,用于存储待执行的任务。然后创建了固定数量的线程池 `workerThreads`,每个线程会不断从任务队列中获取任务并执行。`ThreadPool` 类提供了 `submit` 方法,用于向线程池提交任务。 在 `main` 方法中,我们创建了一个大小为 5 的线程池,并向线程池提交了 10 个任务,每个任务会打印一段文字,并睡眠一秒钟模拟执行任务的耗时。你可以根据实际需求调整线程池的大小和任务的数量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值