亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

線程池的原理與實現(xiàn)詳解

 更新時間:2013年09月14日 10:13:16   作者:  
下面利用C語言來實現(xiàn)一個簡單的線程池,為了使得這個線程池庫使用起來更加方便,特在C實現(xiàn)中加入了一些OO的思想,與Objective-C不同,它僅僅是使用了struct來模擬了c++中的類,其實這種方式在linux內(nèi)核中大量可見

一. 線程池的簡介
通常我們使用多線程的方式是,需要時創(chuàng)建一個新的線程,在這個線程里執(zhí)行特定的任務(wù),然后在任務(wù)完成后退出。這在一般的應(yīng)用里已經(jīng)能夠滿足我們應(yīng)用的需求,畢竟我們并不是什么時候都需要創(chuàng)建大量的線程,并在它們執(zhí)行一個簡單的任務(wù)后銷毀。

但是在一些web、email、database等應(yīng)用里,比如彩鈴,我們的應(yīng)用在任何時候都要準(zhǔn)備應(yīng)對數(shù)目巨大的連接請求,同時,這些請求所要完成的任務(wù)卻又可能非常的簡單,即只占用很少的處理時間。這時,我們的應(yīng)用有可能處于不停的創(chuàng)建線程并銷毀線程的狀態(tài)。雖說比起進(jìn)程的創(chuàng)建,線程的創(chuàng)建時間已經(jīng)大大縮短,但是如果需要頻繁的創(chuàng)建線程,并且每個線程所占用的處理時間又非常簡短,則線程創(chuàng)建和銷毀帶給處理器的額外負(fù)擔(dān)也是很可觀的。

線程池的作用正是在這種情況下有效的降低頻繁創(chuàng)建銷毀線程所帶來的額外開銷。一般來說,線程池都是采用預(yù)創(chuàng)建的技術(shù),在應(yīng)用啟動之初便預(yù)先創(chuàng)建一定數(shù)目的線程。應(yīng)用在運行的過程中,需要時可以從這些線程所組成的線程池里申請分配一個空閑的線程,來執(zhí)行一定的任務(wù),任務(wù)完成后,并不是將線程銷毀,而是將它返還給線程池,由線程池自行管理。如果線程池中預(yù)先分配的線程已經(jīng)全部分配完畢,但此時又有新的任務(wù)請求,則線程池會動態(tài)的創(chuàng)建新的線程去適應(yīng)這個請求。當(dāng)然,有可能,某些時段應(yīng)用并不需要執(zhí)行很多的任務(wù),導(dǎo)致了線程池中的線程大多處于空閑的狀態(tài),為了節(jié)省系統(tǒng)資源,線程池就需要動態(tài)的銷毀其中的一部分空閑線程。因此,線程池都需要一個管理者,按照一定的要求去動態(tài)的維護(hù)其中線程的數(shù)目。

基于上面的技術(shù),線程池將頻繁創(chuàng)建和銷毀線程所帶來的開銷分?jǐn)偟搅嗣總€具體執(zhí)行的任務(wù)上,執(zhí)行的次數(shù)越多,則分?jǐn)偟矫總€任務(wù)上的開銷就越小。

當(dāng)然,如果線程創(chuàng)建銷毀所帶來的開銷與線程執(zhí)行任務(wù)的開銷相比微不足道,可以忽略不計,則線程池并沒有使用的必要。比如,F(xiàn)TP、Telnet等應(yīng)用時。

二. 線程池的設(shè)計
下面利用C語言來實現(xiàn)一個簡單的線程池,為了使得這個線程池庫使用起來更加方便,特在C實現(xiàn)中加入了一些OO的思想,與Objective-C不同,它僅僅是使用了struct來模擬了c++中的類,其實這種方式在linux內(nèi)核中大量可見。

在這個庫里,與用戶有關(guān)的接口主要有:

復(fù)制代碼 代碼如下:

       typedef struct tp_work_desc_s tp_work_desc; //應(yīng)用線程執(zhí)行任務(wù)時所需要的一些信息
       typedef struct tp_work_s tp_work; //線程執(zhí)行的任務(wù)
       typedef struct tp_thread_info_s tp_thread_info; //描述了各個線程id,是否空閑,執(zhí)行的任務(wù)等信息
       typedef struct tp_thread_pool_s tp_thread_pool; // 有關(guān)線程池操作的接口信息
         //thread parm
       struct tp_work_desc_s{
                  ……
        };
       //base thread struct
       struct tp_work_s{
                  //main process function. user interface
                  void (*process_job)(tp_work *this, tp_work_desc *job);
        };
        tp_thread_pool *creat_thread_pool(int min_num, int max_num);

tp_work_desc_s表示應(yīng)用線程執(zhí)行任務(wù)時所需要的一些信息,會被當(dāng)作線程的參數(shù)傳遞給每個線程,依據(jù)應(yīng)用的不同而不同,需要用戶定義結(jié)構(gòu)的內(nèi)容。tp_work_s就是我們希望線程執(zhí)行的任務(wù)了。當(dāng)我們申請分配一個新的線程時,首先要明確的指定這兩個結(jié)構(gòu),即該線程完成什么任務(wù),并且完成這個任務(wù)需要哪些額外的信息。接口函數(shù)creat_thread_pool用來創(chuàng)建一個線程池的實例,使用時需要指定該線程池實例所能容納的最小線程數(shù)min_num和最大線程數(shù)max_num。最小線程數(shù)即線程池創(chuàng)建時預(yù)創(chuàng)建的線程數(shù)目,這個數(shù)目的大小也直接影響了線程池所能起到的效果,如果指定的太小,線程池中預(yù)創(chuàng)建的線程很快就將分配完畢并需要創(chuàng)建新的線程來適應(yīng)不斷的請求,如果指定的太大,則將可能會有大量的空閑線程。我們需要根據(jù)自己應(yīng)用的實際需要進(jìn)行指定。描述線程池的結(jié)構(gòu)如下:
復(fù)制代碼 代碼如下:

        //main thread pool struct
        struct tp_thread_pool_s{
             TPBOOL (*init)(tp_thread_pool *this);
             void (*close)(tp_thread_pool *this);
             void (*process_job)(tp_thread_pool *this, tp_work *worker, tp_work_desc *job);
             int  (*get_thread_by_id)(tp_thread_pool *this, int id);
             TPBOOL (*add_thread)(tp_thread_pool *this);
             TPBOOL (*delete_thread)(tp_thread_pool *this);
              int (*get_tp_status)(tp_thread_pool *this);
              int min_th_num;                //min thread number in the pool
              int cur_th_num;                 //current thread number in the pool
              int max_th_num;         //max thread number in the pool
              pthread_mutex_t tp_lock;
              pthread_t manage_thread_id;  //manage thread id num
              tp_thread_info *thread_info;   //work thread relative thread info
};
         結(jié)構(gòu)tp_thread_info_s描述了各個線程id、是否空閑、執(zhí)行的任務(wù)等信息,用戶并不需要關(guān)心它。
         //thread info
         struct tp_thread_info_s{
              pthread_t          thread_id;         //thread id num
             TPBOOL                   is_busy;    //thread status:true-busy;flase-idle
             pthread_cond_t          thread_cond;
             pthread_mutex_t               thread_lock;
             tp_work                      *th_work;
             tp_work_desc            *th_job;
         };

tp_thread_pool_s結(jié)構(gòu)包含了有關(guān)線程池操作的接口和變量。在使用creat_thread_pool返回一個線程池實例之后,首先要使用明確使用init接口對它進(jìn)行初始化。在這個初始化過程中,線程池會預(yù)創(chuàng)建指定的最小線程數(shù)目的線程,它們都處于阻塞狀態(tài),并不損耗CPU,但是會占用一定的內(nèi)存空間。同時init也會創(chuàng)建一個線程池的管理線程,這個線程會在線程池的運行周期內(nèi)一直執(zhí)行,它將定時的查看分析線程池的狀態(tài),如果線程池中空閑的線程過多,它會刪除部分空閑的線程,當(dāng)然它并不會使所有線程的數(shù)目小于指定的最小線程數(shù)。

在已經(jīng)創(chuàng)建并初始化了線程池之后,我們就可以指定tp_work_desc_s和tp_work_s結(jié)構(gòu),并使用線程池的process_job接口來執(zhí)行它們。這些就是我們使用這個線程池時所需要了解的所有東西。如果不再需要線程池,可以使用close接口銷毀它。

三. 實現(xiàn)代碼
Thread-pool.h(頭文件):

復(fù)制代碼 代碼如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <pthread.h>  
#include <signal.h>  

#ifndef TPBOOL  
typedef int TPBOOL; 
#endif  

#ifndef TRUE  
#define TRUE 1  
#endif  

#ifndef FALSE  
#define FALSE 0  
#endif  

#define BUSY_THRESHOLD 0.5  //(busy thread)/(all thread threshold)  
#define MANAGE_INTERVAL 5   //tp manage thread sleep interval  

typedef struct tp_work_desc_s tp_work_desc; 
typedef struct tp_work_s tp_work; 
typedef struct tp_thread_info_s tp_thread_info; 
typedef struct tp_thread_pool_s tp_thread_pool; 

//thread parm  
struct tp_work_desc_s{ 
    char *inum; //call in  
    char *onum; //call out  
    int chnum;  //channel num  
}; 

//base thread struct  
struct tp_work_s{ 
    //main process function. user interface  
    void (*process_job)(tp_work *this, tp_work_desc *job); 
}; 

//thread info  
struct tp_thread_info_s{ 
    pthread_t       thread_id;  //thread id num  
    TPBOOL          is_busy;    //thread status:true-busy;flase-idle  
    pthread_cond_t          thread_cond;     
    pthread_mutex_t     thread_lock; 
    tp_work         *th_work; 
    tp_work_desc        *th_job; 
}; 

//main thread pool struct  
struct tp_thread_pool_s{ 
    TPBOOL (*init)(tp_thread_pool *this); 
    void (*close)(tp_thread_pool *this); 
    void (*process_job)(tp_thread_pool *this, tp_work *worker, tp_work_desc *job); 
    int  (*get_thread_by_id)(tp_thread_pool *this, int id); 
    TPBOOL (*add_thread)(tp_thread_pool *this); 
    TPBOOL (*delete_thread)(tp_thread_pool *this); 
    int (*get_tp_status)(tp_thread_pool *this); 

    int min_th_num;     //min thread number in the pool  
    int cur_th_num;     //current thread number in the pool  
    int max_th_num;         //max thread number in the pool  
    pthread_mutex_t tp_lock; 
    pthread_t manage_thread_id; //manage thread id num  
    tp_thread_info *thread_info;    //work thread relative thread info  
}; 

tp_thread_pool *creat_thread_pool(int min_num, int max_num);

Thread-pool.c(實現(xiàn)文件):
復(fù)制代碼 代碼如下:

#include "thread-pool.h"  

static void *tp_work_thread(void *pthread); 
static void *tp_manage_thread(void *pthread); 

static TPBOOL tp_init(tp_thread_pool *this); 
static void tp_close(tp_thread_pool *this); 
static void tp_process_job(tp_thread_pool *this, tp_work *worker, tp_work_desc *job); 
static int  tp_get_thread_by_id(tp_thread_pool *this, int id); 
static TPBOOL tp_add_thread(tp_thread_pool *this); 
static TPBOOL tp_delete_thread(tp_thread_pool *this); 
static int  tp_get_tp_status(tp_thread_pool *this); 

/**
  * user interface. creat thread pool.
  * para:
  *     num: min thread number to be created in the pool
  * return:
  *     thread pool struct instance be created successfully
  */ 
tp_thread_pool *creat_thread_pool(int min_num, int max_num){ 
    tp_thread_pool *this; 
    this = (tp_thread_pool*)malloc(sizeof(tp_thread_pool));  

    memset(this, 0, sizeof(tp_thread_pool)); 

    //init member function ponter  
    this->init = tp_init; 
    this->close = tp_close; 
    this->process_job = tp_process_job; 
    this->get_thread_by_id = tp_get_thread_by_id; 
    this->add_thread = tp_add_thread; 
    this->delete_thread = tp_delete_thread; 
    this->get_tp_status = tp_get_tp_status; 

    //init member var  
    this->min_th_num = min_num; 
    this->cur_th_num = this->min_th_num; 
    this->max_th_num = max_num; 
    pthread_mutex_init(&this->tp_lock, NULL); 

    //malloc mem for num thread info struct  
    if(NULL != this->thread_info) 
        free(this->thread_info); 
    this->thread_info = (tp_thread_info*)malloc(sizeof(tp_thread_info)*this->max_th_num); 

    return this; 


 
/**
  * member function reality. thread pool init function.
  * para:
  *     this: thread pool struct instance ponter
  * return:
  *     true: successful; false: failed
  */ 
TPBOOL tp_init(tp_thread_pool *this){ 
    int i; 
    int err; 

    //creat work thread and init work thread info  
    for(i=0;i<this->min_th_num;i++){ 
        pthread_cond_init(&this->thread_info[i].thread_cond, NULL); 
        pthread_mutex_init(&this->thread_info[i].thread_lock, NULL); 

        err = pthread_create(&this->thread_info[i].thread_id, NULL, tp_work_thread, this); 
        if(0 != err){ 
            printf("tp_init: creat work thread failed\n"); 
            return FALSE; 
        } 
        printf("tp_init: creat work thread %d\n", this->thread_info[i].thread_id); 
    } 

    //creat manage thread  
    err = pthread_create(&this->manage_thread_id, NULL, tp_manage_thread, this); 
    if(0 != err){ 
        printf("tp_init: creat manage thread failed\n"); 
        return FALSE; 
    } 
    printf("tp_init: creat manage thread %d\n", this->manage_thread_id); 

    return TRUE; 


/**
  * member function reality. thread pool entirely close function.
  * para:
  *     this: thread pool struct instance ponter
  * return:
  */ 
void tp_close(tp_thread_pool *this){ 
    int i; 

    //close work thread  
    for(i=0;i<this->cur_th_num;i++){ 
        kill(this->thread_info[i].thread_id, SIGKILL); 
        pthread_mutex_destroy(&this->thread_info[i].thread_lock); 
        pthread_cond_destroy(&this->thread_info[i].thread_cond); 
        printf("tp_close: kill work thread %d\n", this->thread_info[i].thread_id); 
    } 

    //close manage thread  
    kill(this->manage_thread_id, SIGKILL); 
    pthread_mutex_destroy(&this->tp_lock); 
    printf("tp_close: kill manage thread %d\n", this->manage_thread_id); 

    //free thread struct  
    free(this->thread_info); 


/**
  * member function reality. main interface opened. 
  * after getting own worker and job, user may use the function to process the task.
  * para:
  *     this: thread pool struct instance ponter
  * worker: user task reality.
  * job: user task para
  * return:
  */ 
void tp_process_job(tp_thread_pool *this, tp_work *worker, tp_work_desc *job){ 
    int i; 
    int tmpid; 

    //fill this->thread_info's relative work key  
    for(i=0;i<this->cur_th_num;i++){ 
        pthread_mutex_lock(&this->thread_info[i].thread_lock); 
        if(!this->thread_info[i].is_busy){ 
            printf("tp_process_job: %d thread idle, thread id is %d\n", i, this->thread_info[i].thread_id); 
            //thread state be set busy before work  
            this->thread_info[i].is_busy = TRUE; 
            pthread_mutex_unlock(&this->thread_info[i].thread_lock); 

            this->thread_info[i].th_work = worker; 
            this->thread_info[i].th_job = job; 

            printf("tp_process_job: informing idle working thread %d, thread id is %d\n", i, this->thread_info[i].thread_id); 
            pthread_cond_signal(&this->thread_info[i].thread_cond); 

            return; 
        } 
        else  
            pthread_mutex_unlock(&this->thread_info[i].thread_lock);      
    }//end of for  

    //if all current thread are busy, new thread is created here  
    pthread_mutex_lock(&this->tp_lock); 
    if( this->add_thread(this) ){ 
        i = this->cur_th_num - 1; 
        tmpid = this->thread_info[i].thread_id; 
        this->thread_info[i].th_work = worker; 
        this->thread_info[i].th_job = job; 
    } 
    pthread_mutex_unlock(&this->tp_lock); 

    //send cond to work thread  
    printf("tp_process_job: informing idle working thread %d, thread id is %d\n", i, this->thread_info[i].thread_id); 
    pthread_cond_signal(&this->thread_info[i].thread_cond); 
    return;  


/**
  * member function reality. get real thread by thread id num.
  * para:
  *     this: thread pool struct instance ponter
  * id: thread id num
  * return:
  *     seq num in thread info struct array
  */ 
int tp_get_thread_by_id(tp_thread_pool *this, int id){ 
    int i; 

    for(i=0;i<this->cur_th_num;i++){ 
        if(id == this->thread_info[i].thread_id) 
            return i; 
    } 

    return -1; 


/**
  * member function reality. add new thread into the pool.
  * para:
  *     this: thread pool struct instance ponter
  * return:
  *     true: successful; false: failed
  */ 
static TPBOOL tp_add_thread(tp_thread_pool *this){ 
    int err; 
    tp_thread_info *new_thread; 

    if( this->max_th_num <= this->cur_th_num ) 
        return FALSE; 

    //malloc new thread info struct  
    new_thread = &this->thread_info[this->cur_th_num]; 

    //init new thread's cond & mutex  
    pthread_cond_init(&new_thread->thread_cond, NULL); 
    pthread_mutex_init(&new_thread->thread_lock, NULL); 

    //init status is busy  
    new_thread->is_busy = TRUE; 

    //add current thread number in the pool.  
    this->cur_th_num++; 

    err = pthread_create(&new_thread->thread_id, NULL, tp_work_thread, this); 
    if(0 != err){ 
        free(new_thread); 
        return FALSE; 
    } 
    printf("tp_add_thread: creat work thread %d\n", this->thread_info[this->cur_th_num-1].thread_id); 

    return TRUE; 


/**
  * member function reality. delete idle thread in the pool.
  * only delete last idle thread in the pool.
  * para:
  *     this: thread pool struct instance ponter
  * return:
  *     true: successful; false: failed
  */ 
static TPBOOL tp_delete_thread(tp_thread_pool *this){ 
    //current thread num can't < min thread num  
    if(this->cur_th_num <= this->min_th_num) return FALSE; 

    //if last thread is busy, do nothing  
    if(this->thread_info[this->cur_th_num-1].is_busy) return FALSE; 

    //kill the idle thread and free info struct  
    kill(this->thread_info[this->cur_th_num-1].thread_id, SIGKILL); 
    pthread_mutex_destroy(&this->thread_info[this->cur_th_num-1].thread_lock); 
    pthread_cond_destroy(&this->thread_info[this->cur_th_num-1].thread_cond); 

    //after deleting idle thread, current thread num -1  
    this->cur_th_num--; 

    return TRUE; 


/**
  * member function reality. get current thread pool status:idle, normal, busy, .etc.
  * para:
  *     this: thread pool struct instance ponter
  * return:
  *     0: idle; 1: normal or busy(don't process)
  */ 
static int  tp_get_tp_status(tp_thread_pool *this){ 
    float busy_num = 0.0; 
    int i; 

    //get busy thread number  
    for(i=0;i<this->cur_th_num;i++){ 
        if(this->thread_info[i].is_busy) 
            busy_num++; 
    } 

    //0.2? or other num?  
    if(busy_num/(this->cur_th_num) < BUSY_THRESHOLD) 
        return 0;//idle status  
    else 
        return 1;//busy or normal status      


/**
  * internal interface. real work thread.
  * para:
  *     pthread: thread pool struct ponter
  * return:
  */ 
static void *tp_work_thread(void *pthread){ 
    pthread_t curid;//current thread id  
    int nseq;//current thread seq in the this->thread_info array  
    tp_thread_pool *this = (tp_thread_pool*)pthread;//main thread pool struct instance  

    //get current thread id  
    curid = pthread_self(); 

    //get current thread's seq in the thread info struct array.  
    nseq = this->get_thread_by_id(this, curid); 
    if(nseq < 0) 
        return; 
    printf("entering working thread %d, thread id is %d\n", nseq, curid); 

    //wait cond for processing real job.  
    while( TRUE ){ 
        pthread_mutex_lock(&this->thread_info[nseq].thread_lock); 
        pthread_cond_wait(&this->thread_info[nseq].thread_cond, &this->thread_info[nseq].thread_lock); 
        pthread_mutex_unlock(&this->thread_info[nseq].thread_lock);       

        printf("%d thread do work!\n", pthread_self()); 

        tp_work *work = this->thread_info[nseq].th_work; 
        tp_work_desc *job = this->thread_info[nseq].th_job; 

        //process  
        work->process_job(work, job); 

        //thread state be set idle after work  
        pthread_mutex_lock(&this->thread_info[nseq].thread_lock);         
        this->thread_info[nseq].is_busy = FALSE; 
        pthread_mutex_unlock(&this->thread_info[nseq].thread_lock); 

        printf("%d do work over\n", pthread_self()); 
    }    


/**
  * internal interface. manage thread pool to delete idle thread.
  * para:
  *     pthread: thread pool struct ponter
  * return:
  */ 
static void *tp_manage_thread(void *pthread){ 
    tp_thread_pool *this = (tp_thread_pool*)pthread;//main thread pool struct instance  

    //1?  
    sleep(MANAGE_INTERVAL); 

    do{ 
        if( this->get_tp_status(this) == 0 ){ 
            do{ 
                if( !this->delete_thread(this) ) 
                    break; 
            }while(TRUE); 
        }//end for if  

        //1?  
        sleep(MANAGE_INTERVAL); 
    }while(TRUE); 


四. 數(shù)據(jù)庫連接池介紹   
數(shù)據(jù)庫連接是一種關(guān)鍵的有限的昂貴的資源,這一點在多用戶的網(wǎng)頁應(yīng)用程序中體現(xiàn)得尤為突出。

一個數(shù)據(jù)庫連接對象均對應(yīng)一個物理數(shù)據(jù)庫連接,每次操作都打開一個物理連接,使用完都關(guān)閉連接,這樣造成系統(tǒng)的 性能低下。 數(shù)據(jù)庫連接池的解決方案是在應(yīng)用程序啟動時建立足夠的數(shù)據(jù)庫連接,并講這些連接組成一個連接池(簡單說:在一個“池”里放了好多半成品的數(shù)據(jù)庫聯(lián)接對象),由應(yīng)用程序動態(tài)地對池中的連接進(jìn)行申請、使用和釋放。對于多于連接池中連接數(shù)的并發(fā)請求,應(yīng)該在請求隊列中排隊等待。并且應(yīng)用程序可以根據(jù)池中連接的使用率,動態(tài)增加或減少池中的連接數(shù)。

連接池技術(shù)盡可能多地重用了消耗內(nèi)存地資源,大大節(jié)省了內(nèi)存,提高了服務(wù)器地服務(wù)效率,能夠支持更多的客戶服務(wù)。通過使用連接池,將大大提高程序運行效率,同時,我們可以通過其自身的管理機制來監(jiān)視數(shù)據(jù)庫連接的數(shù)量、使用情況等。

1)  最小連接數(shù)是連接池一直保持的數(shù)據(jù)庫連接,所以如果應(yīng)用程序?qū)?shù)據(jù)庫連接的使用量不大,將會有大量的數(shù)據(jù)庫連接資源被浪費;

2)  最大連接數(shù)是連接池能申請的最大連接數(shù),如果數(shù)據(jù)庫連接請求超過此數(shù),后面的數(shù)據(jù)庫連接請求將被加入到等待隊列中,這會影響之后的數(shù)據(jù)庫操作。

相關(guān)文章

  • C語言實現(xiàn)用?*?打印X形圖案

    C語言實現(xiàn)用?*?打印X形圖案

    這篇文章主要介紹了C語言實現(xiàn)用?*?打印X形圖案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷

    C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷

    這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Objective-C中常用的結(jié)構(gòu)體NSRange,NSPoint,NSSize(CGSize),NSRect實例分析

    Objective-C中常用的結(jié)構(gòu)體NSRange,NSPoint,NSSize(CGSize),NSRect實例分析

    這篇文章主要介紹了Objective-C中常用的結(jié)構(gòu)體NSRange,NSPoint,NSSize(CGSize),NSRect實例分析,有助于更加直觀的理解Object-C常用的結(jié)構(gòu)體,需要的朋友可以參考下
    2014-07-07
  • c++實現(xiàn)俄羅斯方塊游戲代碼

    c++實現(xiàn)俄羅斯方塊游戲代碼

    大家好,本篇文章主要講的是c++實現(xiàn)俄羅斯方塊游戲代碼,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • 淺談在函數(shù)中返回動態(tài)的內(nèi)存

    淺談在函數(shù)中返回動態(tài)的內(nèi)存

    下面小編就為大家?guī)硪黄獪\談在函數(shù)中返回動態(tài)的內(nèi)存。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • c++的glog與spdlog的性能對比測試分析

    c++的glog與spdlog的性能對比測試分析

    這篇文章主要為大家介紹了c++的glog與spdlog的性能對比測試分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • C++ 再識類和對象

    C++ 再識類和對象

    類是創(chuàng)建對象的模板,一個類可以創(chuàng)建多個對象,每個對象都是類類型的一個變量;創(chuàng)建對象的過程也叫類的實例化。每個對象都是類的一個具體實例(Instance),擁有類的成員變量和成員函數(shù)
    2021-10-10
  • Qt編寫地圖實現(xiàn)動態(tài)點位標(biāo)注的示例代碼

    Qt編寫地圖實現(xiàn)動態(tài)點位標(biāo)注的示例代碼

    動態(tài)點位標(biāo)注是定制的一個功能模塊,提供直接地圖上選點設(shè)置標(biāo)記點,點位信息用結(jié)構(gòu)體存儲,其中包括了經(jīng)度、緯度、速度、時間等信息。本文將介紹實現(xiàn)這一功能的示例代碼,需要的可以參考一下
    2022-01-01
  • C++獲取文件大小的4種常見技巧分享

    C++獲取文件大小的4種常見技巧分享

    這篇文章主要介紹了C++獲取文件大小的4種常見技巧分享,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • c++中處理相關(guān)數(shù)學(xué)函數(shù)

    c++中處理相關(guān)數(shù)學(xué)函數(shù)

    數(shù)學(xué)庫函數(shù)聲明在 math.h 中,主要有:
    2013-04-04

最新評論