多线程的问题、求解各位大神。!

半城-樱花 2014-04-25 05:20:41
比如说我要开10条线程,10 条线程都是取数据插入数据库。
有没有10条线程同时运行取数据的时候,把取回来的数据存进一个容器里面,但是又互不干涉,然判断容器装的数据大于多少(这里设置100 条),再开连接把这10条线程容器装的数据插入数据库、。

原本项目逻辑是这样的:每开一条线程,取回来一条数据,打开连接,插入,关闭。 很简单!!!
但是这样循环开线程,循环连接数据库,循环关闭。总有问题吧!、每一条线程过来只带一条数据,但是都要开一次连接,再关闭,这样太频繁了,所以要求修改!!

要求我设定开多少条线程,每一条线程带多少条数据,然后开一次数据库连接,把每一条线程带的数据插入数据库,再关闭连接。。
我现在测试的是开了20 条线程,依然是每一条线程取1条数据,然后通过方法拼成 insert 语句,我再把返回来的 SQL 语句拼接起来,然后判断大于100再插入数据库,这样也是只需要开一次连接就批量插入100条数据了。
但是那个经理说不行,我这样是开了20 条线程,但是插入的时候只插入了100条数据,他要的是20 条线程,每一条线程都要带100条,再开数据库之后执行这20条线程全部插入数据库,这样一次插入2000条数据(汗、和我的100条差了太多)。

但是我想不明白,怎么可以同时运行20 条线程,我上面的测试就是每一条线程取1 条数据过来,然后拼接sql 语句,在拼接完成之后那条线程不是工作完了么?第二 条在继续过来拼接,当拼接满100 条的时候那条线程就会带着这些拼好的语句插入数据库,然后清空。。就是这样一直循环着。

但要求每一条线程都要带100条,再开数据库之后执行这20条线程全部插入数据库,这样一次插入2000条数据,我就想不明白了。。这个请求大家。、
...全文
372 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
淡写你的回忆 2014-05-06
  • 打赏
  • 举报
回复
- -好复杂的样子我还准备。。。看看我能不能从中学到啥哩
半城-樱花 2014-05-05
  • 打赏
  • 举报
回复
引用 14 楼 xianglitian 的回复:
数据库有并发控制 并不是你真的开了20个线程 真的同时操作就真的能同时存储的 因为不知道你具体的数据组织方式和具体的操作方法 所以不好给什么建议 类似的问题我遇到过 后来不用数据库自己写随机文件处理了 你或许可以用类似的方式 开一个随机文件作为缓存 20个线程可以同时按事先的约定操作随机文件 另开一个线程监控另外20个线程的完成情况 如果全部完成就一次性将文件内容全部倒入数据库 随机文件可以用内存映射文件来保证效率 倒入数据库我记得sql server有支持文件倒入的方法 建议而已 有不当之处还请见谅
谢谢、问题已解决。。
半城-樱花 2014-05-05
  • 打赏
  • 举报
回复
问题已经解决、谢谢大家!!!
半城-樱花 2014-05-05
  • 打赏
  • 举报
回复
引用 17 楼 worldy 的回复:
[quote=引用 15 楼 u010340690 的回复:] [quote=引用 13 楼 worldy 的回复:] [quote=引用 12 楼 u010340690 的回复:] [quote=引用 10 楼 worldy 的回复:] [quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。[/quote] 那你做的和我说的还是不一样,我说的是,每个线程获取自己的100条数据,然后插入,每个线程各管各自的数据 [/quote] 我就是卡在每条线程取100条数据这里啊!!之前我是建一个全局的集合的,即是多条线程共用一个集合,现在修改为局部集合。即是每开一条线程就new 一个集合。我取数据一次只能取一条的,要想在集合里存满100条数据我试过了是不行的,每取一条数据过来都要经过 new 一个集合这步骤。。。[/quote] 肯定行的,不行肯定是你的代码有什么问题 并且集合可以作为线程的局部变量对待,因为线程只要没有退出,变量将一直存在[/quote]谢谢你了、已经解决了。原来在取数据哪里加个循环就可以了、循环取。
worldy 2014-05-04
  • 打赏
  • 举报
回复
引用 15 楼 u010340690 的回复:
[quote=引用 13 楼 worldy 的回复:] [quote=引用 12 楼 u010340690 的回复:] [quote=引用 10 楼 worldy 的回复:] [quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。[/quote] 那你做的和我说的还是不一样,我说的是,每个线程获取自己的100条数据,然后插入,每个线程各管各自的数据 [/quote] 我就是卡在每条线程取100条数据这里啊!!之前我是建一个全局的集合的,即是多条线程共用一个集合,现在修改为局部集合。即是每开一条线程就new 一个集合。我取数据一次只能取一条的,要想在集合里存满100条数据我试过了是不行的,每取一条数据过来都要经过 new 一个集合这步骤。。。[/quote] 肯定行的,不行肯定是你的代码有什么问题 并且集合可以作为线程的局部变量对待,因为线程只要没有退出,变量将一直存在
半城-樱花 2014-05-04
  • 打赏
  • 举报
回复
引用 15 楼 u010340690 的回复:
[quote=引用 13 楼 worldy 的回复:] [quote=引用 12 楼 u010340690 的回复:] [quote=引用 10 楼 worldy 的回复:] [quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。[/quote] 那你做的和我说的还是不一样,我说的是,每个线程获取自己的100条数据,然后插入,每个线程各管各自的数据 [/quote] 我就是卡在每条线程取100条数据这里啊!!之前我是建一个全局的集合的,即是多条线程共用一个集合,现在修改为局部集合。即是每开一条线程就new 一个集合。我取数据一次只能取一条的,要想在集合里存满100条数据我试过了是不行的,每取一条数据过来都要经过 new 一个集合这步骤。。。[/quote] 还望大神赐教啊、我就是一个实习生啊!!!
半城-樱花 2014-05-04
  • 打赏
  • 举报
回复
引用 13 楼 worldy 的回复:
[quote=引用 12 楼 u010340690 的回复:] [quote=引用 10 楼 worldy 的回复:] [quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。[/quote] 那你做的和我说的还是不一样,我说的是,每个线程获取自己的100条数据,然后插入,每个线程各管各自的数据 [/quote] 我就是卡在每条线程取100条数据这里啊!!之前我是建一个全局的集合的,即是多条线程共用一个集合,现在修改为局部集合。即是每开一条线程就new 一个集合。我取数据一次只能取一条的,要想在集合里存满100条数据我试过了是不行的,每取一条数据过来都要经过 new 一个集合这步骤。。。
panshoup 2014-05-04
  • 打赏
  • 举报
回复
引用 21 楼 zhao4zhong1 的回复:
演示“多线程+日志+线程池+锁”工作过程的经典代码。
学习学习赵老师
半城-樱花 2014-05-04
  • 打赏
  • 举报
回复
引用 21 楼 zhao4zhong1 的回复:
演示“多线程+日志+线程池+锁”工作过程的经典代码。
表示看不懂、太复习了。。。。。貌似和我的问题有关联么??
yyps 2014-05-04
  • 打赏
  • 举报
回复
能用定时器的就不用线程,能用一个线程的就不要用多个线程。线程多了,容易出问题,出了问题还难排查。
赵4老师 2014-05-04
  • 打赏
  • 举报
回复
演示“多线程+日志+线程池+锁”工作过程的经典代码。
半城-樱花 2014-05-04
  • 打赏
  • 举报
回复
引用 19 楼 zhao4zhong1 的回复:
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer,
//a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理,
//在处理的时候每次从新buffer中取两个字节打印
#ifdef WIN32
    #pragma warning(disable:4996)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <process.h>
    #include <io.h>
    #define  MYVOID             void
    #define  vsnprintf          _vsnprintf
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  MYVOID             void *
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
void sleep_ms(int ms) {
    Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
    usleep(ms*1000);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt||0==pszFmt[0]) return;
    vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
        } else {
            fclose(flog);
        }
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
#define ASIZE    200
#define BSIZE    240
#define CSIZE      2
char Abuf[ASIZE];
char Cbuf[CSIZE];
CRITICAL_SECTION cs_HEX ;
CRITICAL_SECTION cs_BBB ;
struct FIFO_BUFFER {
    int  head;
    int  tail;
    int  size;
    char data[BSIZE];
} BBB;
int No_Loop=0;
void HexDump(int cn,char *buf,int len) {
    int i,j,k;
    char binstr[80];

    Lock(&cs_HEX);
    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%03d %04x -",cn,i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            Log("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        Log("%s\n",binstr);
    }
    Unlock(&cs_HEX);
}
int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    lent=0;
    Lock(cs);
    if (fbuf->size>=len) {
        lent=len;
        if (fbuf->head+lent>BSIZE) {
            len1=BSIZE-fbuf->head;
            memcpy(buf     ,fbuf->data+fbuf->head,len1);
            len2=lent-len1;
            memcpy(buf+len1,fbuf->data           ,len2);
            fbuf->head=len2;
        } else {
            memcpy(buf     ,fbuf->data+fbuf->head,lent);
            fbuf->head+=lent;
        }
        fbuf->size-=lent;
    }
    Unlock(cs);
    return lent;
}
MYVOID thdB(void *pcn) {
    char        *recv_buf;
    int          recv_nbytes;
    int          cn;
    int          wc;
    int          pb;

    cn=(int)pcn;
    Log("%03d thdB              thread begin...\n",cn);
    while (1) {
        sleep_ms(10);
        recv_buf=(char *)Cbuf;
        recv_nbytes=CSIZE;
        wc=0;
        while (1) {
            pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);
            if (pb) {
                Log("%03d recv %d bytes\n",cn,pb);
                HexDump(cn,recv_buf,pb);
                sleep_ms(1);
            } else {
                sleep_ms(1000);
            }
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef WIN32
    pthread_exit(NULL);
#endif
}
int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    Lock(cs);
    lent=len;
    if (fbuf->size+lent>BSIZE) {
        lent=BSIZE-fbuf->size;
    }
    if (fbuf->tail+lent>BSIZE) {
        len1=BSIZE-fbuf->tail;
        memcpy(fbuf->data+fbuf->tail,buf     ,len1);
        len2=lent-len1;
        memcpy(fbuf->data           ,buf+len1,len2);
        fbuf->tail=len2;
    } else {
        memcpy(fbuf->data+fbuf->tail,buf     ,lent);
        fbuf->tail+=lent;
    }
    fbuf->size+=lent;
    Unlock(cs);
    return lent;
}
MYVOID thdA(void *pcn) {
    char        *send_buf;
    int          send_nbytes;
    int          cn;
    int          wc;
    int           a;
    int          pa;

    cn=(int)pcn;
    Log("%03d thdA              thread begin...\n",cn);
    a=0;
    while (1) {
        sleep_ms(100);
        memset(Abuf,a,ASIZE);
        a=(a+1)%256;
        if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop
        send_buf=(char *)Abuf;
        send_nbytes=ASIZE;
        Log("%03d sending %d bytes\n",cn,send_nbytes);
        HexDump(cn,send_buf,send_nbytes);
        wc=0;
        while (1) {
            pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);
            Log("%03d sent %d bytes\n",cn,pa);
            HexDump(cn,send_buf,pa);
            send_buf+=pa;
            send_nbytes-=pa;
            if (send_nbytes<=0) break;//
            sleep_ms(1000);
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef WIN32
    pthread_exit(NULL);
#endif
}
int main() {
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
    InitializeCriticalSection(&cs_HEX );
    InitializeCriticalSection(&cs_BBB );
#else
    pthread_t threads[2];
    int threadsN;
    int rc;
    pthread_mutex_init(&cs_log,NULL);
    pthread_mutex_init(&cs_HEX,NULL);
    pthread_mutex_init(&cs_BBB,NULL);
#endif
    Log("Start===========================================================\n");

    BBB.head=0;
    BBB.tail=0;
    BBB.size=0;

#ifdef WIN32
    _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);
    _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2);
#else
    threadsN=0;
    rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
    rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif

    if (!access("No_Loop",0)) {
        remove("No_Loop");
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    while (1) {
        sleep_ms(1000);
        if (No_Loop) break;//
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    sleep_ms(3000);
    Log("End=============================================================\n");
#ifdef WIN32
    DeleteCriticalSection(&cs_BBB );
    DeleteCriticalSection(&cs_HEX );
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_BBB);
    pthread_mutex_destroy(&cs_HEX);
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
大哥、你这是干啥的??、
赵4老师 2014-05-04
  • 打赏
  • 举报
回复
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer,
//a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理,
//在处理的时候每次从新buffer中取两个字节打印
#ifdef WIN32
    #pragma warning(disable:4996)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <process.h>
    #include <io.h>
    #define  MYVOID             void
    #define  vsnprintf          _vsnprintf
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  MYVOID             void *
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
void sleep_ms(int ms) {
    Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
    usleep(ms*1000);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt||0==pszFmt[0]) return;
    vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
        } else {
            fclose(flog);
        }
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
#define ASIZE    200
#define BSIZE    240
#define CSIZE      2
char Abuf[ASIZE];
char Cbuf[CSIZE];
CRITICAL_SECTION cs_HEX ;
CRITICAL_SECTION cs_BBB ;
struct FIFO_BUFFER {
    int  head;
    int  tail;
    int  size;
    char data[BSIZE];
} BBB;
int No_Loop=0;
void HexDump(int cn,char *buf,int len) {
    int i,j,k;
    char binstr[80];

    Lock(&cs_HEX);
    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%03d %04x -",cn,i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            Log("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        Log("%s\n",binstr);
    }
    Unlock(&cs_HEX);
}
int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    lent=0;
    Lock(cs);
    if (fbuf->size>=len) {
        lent=len;
        if (fbuf->head+lent>BSIZE) {
            len1=BSIZE-fbuf->head;
            memcpy(buf     ,fbuf->data+fbuf->head,len1);
            len2=lent-len1;
            memcpy(buf+len1,fbuf->data           ,len2);
            fbuf->head=len2;
        } else {
            memcpy(buf     ,fbuf->data+fbuf->head,lent);
            fbuf->head+=lent;
        }
        fbuf->size-=lent;
    }
    Unlock(cs);
    return lent;
}
MYVOID thdB(void *pcn) {
    char        *recv_buf;
    int          recv_nbytes;
    int          cn;
    int          wc;
    int          pb;

    cn=(int)pcn;
    Log("%03d thdB              thread begin...\n",cn);
    while (1) {
        sleep_ms(10);
        recv_buf=(char *)Cbuf;
        recv_nbytes=CSIZE;
        wc=0;
        while (1) {
            pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);
            if (pb) {
                Log("%03d recv %d bytes\n",cn,pb);
                HexDump(cn,recv_buf,pb);
                sleep_ms(1);
            } else {
                sleep_ms(1000);
            }
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef WIN32
    pthread_exit(NULL);
#endif
}
int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
    int lent,len1,len2;

    Lock(cs);
    lent=len;
    if (fbuf->size+lent>BSIZE) {
        lent=BSIZE-fbuf->size;
    }
    if (fbuf->tail+lent>BSIZE) {
        len1=BSIZE-fbuf->tail;
        memcpy(fbuf->data+fbuf->tail,buf     ,len1);
        len2=lent-len1;
        memcpy(fbuf->data           ,buf+len1,len2);
        fbuf->tail=len2;
    } else {
        memcpy(fbuf->data+fbuf->tail,buf     ,lent);
        fbuf->tail+=lent;
    }
    fbuf->size+=lent;
    Unlock(cs);
    return lent;
}
MYVOID thdA(void *pcn) {
    char        *send_buf;
    int          send_nbytes;
    int          cn;
    int          wc;
    int           a;
    int          pa;

    cn=(int)pcn;
    Log("%03d thdA              thread begin...\n",cn);
    a=0;
    while (1) {
        sleep_ms(100);
        memset(Abuf,a,ASIZE);
        a=(a+1)%256;
        if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop
        send_buf=(char *)Abuf;
        send_nbytes=ASIZE;
        Log("%03d sending %d bytes\n",cn,send_nbytes);
        HexDump(cn,send_buf,send_nbytes);
        wc=0;
        while (1) {
            pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);
            Log("%03d sent %d bytes\n",cn,pa);
            HexDump(cn,send_buf,pa);
            send_buf+=pa;
            send_nbytes-=pa;
            if (send_nbytes<=0) break;//
            sleep_ms(1000);
            if (No_Loop) break;//
            wc++;
            if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
        }
        if (No_Loop) break;//
    }
#ifndef WIN32
    pthread_exit(NULL);
#endif
}
int main() {
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
    InitializeCriticalSection(&cs_HEX );
    InitializeCriticalSection(&cs_BBB );
#else
    pthread_t threads[2];
    int threadsN;
    int rc;
    pthread_mutex_init(&cs_log,NULL);
    pthread_mutex_init(&cs_HEX,NULL);
    pthread_mutex_init(&cs_BBB,NULL);
#endif
    Log("Start===========================================================\n");

    BBB.head=0;
    BBB.tail=0;
    BBB.size=0;

#ifdef WIN32
    _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);
    _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2);
#else
    threadsN=0;
    rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
    rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif

    if (!access("No_Loop",0)) {
        remove("No_Loop");
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    while (1) {
        sleep_ms(1000);
        if (No_Loop) break;//
        if (!access("No_Loop",0)) {
            No_Loop=1;
        }
    }
    sleep_ms(3000);
    Log("End=============================================================\n");
#ifdef WIN32
    DeleteCriticalSection(&cs_BBB );
    DeleteCriticalSection(&cs_HEX );
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_BBB);
    pthread_mutex_destroy(&cs_HEX);
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
半城-樱花 2014-05-04
  • 打赏
  • 举报
回复
引用 17 楼 worldy 的回复:
[quote=引用 15 楼 u010340690 的回复:] [quote=引用 13 楼 worldy 的回复:] [quote=引用 12 楼 u010340690 的回复:] [quote=引用 10 楼 worldy 的回复:] [quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。[/quote] 那你做的和我说的还是不一样,我说的是,每个线程获取自己的100条数据,然后插入,每个线程各管各自的数据 [/quote] 我就是卡在每条线程取100条数据这里啊!!之前我是建一个全局的集合的,即是多条线程共用一个集合,现在修改为局部集合。即是每开一条线程就new 一个集合。我取数据一次只能取一条的,要想在集合里存满100条数据我试过了是不行的,每取一条数据过来都要经过 new 一个集合这步骤。。。[/quote] 肯定行的,不行肯定是你的代码有什么问题 并且集合可以作为线程的局部变量对待,因为线程只要没有退出,变量将一直存在[/quote]
 class Program
    {
        //<!-- ServerName 服务器主机名字 -->
        //<!-- Server :mysql服务器ip -->
        //<!-- ServerLocation 服务器位置,只可为两位字符代表 -->
        //<!-- SQSURL HTTPSQS日志队列获取地址 注意地址结尾要加/? -->
        //<!-- SQSAUTH  HTTPSQS约定口令-->
        //<!-- TimeSpan 每隔多长时间执行一次,值为(秒数 X 1000) -->
        //<!-- ExecNumber 一次执行读取多少日志 -->
        //<!-- LOGSQSNAME 队列名字 -->

        static object obj1 = new object();
        static object obj2 = new object();
        static int Timespan = int.Parse(System.Configuration.ConfigurationManager.AppSettings["TimeSpan"]);
        static int ExecNumber = int.Parse(System.Configuration.ConfigurationManager.AppSettings["ExecNumber"]);
        static string DBHost = System.Configuration.ConfigurationManager.AppSettings["Server"];
        static string SqsHost = System.Configuration.ConfigurationManager.AppSettings["SQSURL"].Replace("http://", "").Split(':')[0];
        static System.Timers.Timer timer = new System.Timers.Timer(Timespan);
        //对象集合  全部变量 多条线程共用
        static List<ModelManger> DataList = new List<ModelManger>();

        //static List<ModelManger> list = null;

        static void Main(string[] args)
        {
            Thread.Sleep(1000);
            try
            {
                LogWrapper logWrapper = new LogWrapper();
                //写入日志文件,本地
                logWrapper.BuildLogFile("ServiceStart------------------------------", "Pause 1s", SqsHost, DBHost, "", "", "", "", "", "", "", "", "", "", "");
            }
            catch
            {

            }
            //通过委托调用 Commit 方法
            timer.Elapsed += new System.Timers.ElapsedEventHandler(Commit);
            timer.AutoReset = true;
            timer.Enabled = true;
            timer.Start();
            System.Windows.Forms.Application.Run();
        }

        protected static void OnStop()
        {

            timer.Enabled = false;
            timer.AutoReset = false;
            timer.Stop();
            timer.Dispose();
        }

        protected static void Commit(object sender, ElapsedEventArgs e)
        {
            try
            {
                if (DateTime.Now.Hour != 3)
                {
                    ThreadPool.SetMaxThreads(20, 10);

                    using (Ping p = new Ping())
                    {
                        PingReply replysqs = p.Send(SqsHost, 1000);

                        PingReply replydb = p.Send(DBHost, 1000);
                        if (replysqs.Status == IPStatus.Success && replydb.Status == IPStatus.Success)
                        {
                            for (int i = 0; i < ExecNumber; i++)
                            {
                                ThreadPool.QueueUserWorkItem(ExecLogger);
                            }
                        }
                        else
                        {
                            try
                            {
                                lock (obj1)
                                {
                                    LogWrapper logWrapper = new LogWrapper();

                                    logWrapper.BuildLogFile("UnableReachNetwork", "Pause 1s", SqsHost, DBHost, "", "", "", "", "", "", "", "", "", "", "");
                                }
                            }
                            catch
                            {

                            }
                        }
                    }
                }
                else
                {
                    if (DateTime.Now.Hour == 3 && DateTime.Now.Minute == 0 && DateTime.Now.Second == 1)
                    {
                        LogSQS log = new LogSQS();

                        log.Time = "{0:yyyy-MM-dd HH:mm:ss,ffff}".FormatWith(DateTime.Now);

                        log.Reset();
                    }
                }
            }
            catch (Exception ex)
            {
                LogWrapper logWrapper = new LogWrapper();

                logWrapper.BuildLogFile("ThreadPoolException", ex.ToString(), "", "", "", "", "", "", "", "", "", "", "", "", "");

            }
        }

        protected static void ExecLogger(object obj)
        {
            try
            {
                lock (obj1)
                {
                    LogSQS log = new LogSQS();
                    log.Time = "{0:yyyy-MM-dd HH:mm:ss,ffff}".FormatWith(DateTime.Now);
                    log.Receive(DataList); //去队列取数据方法
                    if (DataList.Count > 9)
                    {
                        using (LoggerDao logger = new LoggerDao())
                        {
                            //插入数据库
                            logger.InsertOrUpdate(DataList, log.sbData.ToString());
                        }
                    }
                    else
                    {
                        return;
                    }
                }
            }

            catch (Exception ex)
            {
                try
                {

                    LogWrapper logWrapper = new LogWrapper();

                    logWrapper.BuildLogFile("ExecLogger", System.DateTime.Now.ToString(), ex.Message, "", "", "", "", "", "", "", "", "", "", "", "");

                }
                catch
                {

                }
            }
        }
    }
}

如果是代码问题、那你帮我看看我该在哪里创建线程的局部变量集合???
向立天 2014-04-30
  • 打赏
  • 举报
回复
数据库有并发控制 并不是你真的开了20个线程 真的同时操作就真的能同时存储的 因为不知道你具体的数据组织方式和具体的操作方法 所以不好给什么建议 类似的问题我遇到过 后来不用数据库自己写随机文件处理了 你或许可以用类似的方式 开一个随机文件作为缓存 20个线程可以同时按事先的约定操作随机文件 另开一个线程监控另外20个线程的完成情况 如果全部完成就一次性将文件内容全部倒入数据库 随机文件可以用内存映射文件来保证效率 倒入数据库我记得sql server有支持文件倒入的方法 建议而已 有不当之处还请见谅
worldy 2014-04-30
  • 打赏
  • 举报
回复
引用 12 楼 u010340690 的回复:
[quote=引用 10 楼 worldy 的回复:] [quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。[/quote] 那你做的和我说的还是不一样,我说的是,每个线程获取自己的100条数据,然后插入,每个线程各管各自的数据
半城-樱花 2014-04-29
  • 打赏
  • 举报
回复
引用 10 楼 worldy 的回复:
[quote=引用 9 楼 u010340690 的回复:] [quote=引用 8 楼 worldy 的回复:] [quote=引用 7 楼 u010340690 的回复:] [quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分 [/quote]你说的和我现在的就是一样啊,我不就把是每取一条数据过来之后就拼接成插入语句么,然后把这些语句拼接起来,等拼够多少(100)条的时候再插入。但是这样只能插入自己设置的条数啊。也就是100条。[/quote] 做到这样就挺好啊,不然还要怎么样呢?[/quote]要是要求是这样我还用这么烦啊、哎!比如说开10条线程,每一条线程取一条数据过来,拼接起来,10条线程不停的取数据,轮流这拼接,这条拼接完下一条继续,拼够100条的时候就又那条线程运 行插入数据库的操作,其他9条线程在等待,操作完成后清空,在继续开始拼接。。 但是这样问题来了,我这样开了10 条线程,最后只有一个线程执行插入数据库的方法,一次也就插入100条。经理要的要求不是这样的,他要的效果是最后操作插入数据库的时候,10 条线程都要运行,并且每一条线程都要带100条数据的。。
worldy 2014-04-28
  • 打赏
  • 举报
回复
引用 7 楼 u010340690 的回复:
[quote=引用 2 楼 worldy 的回复:] lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。[/quote] 见红色部分
半城-樱花 2014-04-28
  • 打赏
  • 举报
回复
引用 2 楼 worldy 的回复:
lz的意思,不知道理解对不对,lz是否可以每个线程每取到一条数据,就将数据放入线程的缓存区,等到缓存区有100条数据的之后,就转入保存数据的操作,数据保存完成之后,线程继续转入取数据操作;或者到线程缓存区有100条数据之后,就启动一个保存数据的线程。 话说回来,并发同性质任务操作的并发线程数最好和cpu的内核数匹配,开太多的多线程不仅无法提高整体效率,反而是降低整体效率,原因你懂的
那你说说我这个问题怎么解决??现在不是开多少线程的问题,而是插入数据库的问题。
半城-樱花 2014-04-28
  • 打赏
  • 举报
回复
引用 1 楼 mayudong1 的回复:
有一种东西叫线程池 还有一种东西叫连接池
这个都有用到啊、都在配置文件哪里给配置了。
加载更多回复(7)

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧