项目要求

1.基本

  用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件;实现复制到指定文件夹的全部文件夹。

2.扩充功能

  显示进度条;拷贝耗时统计;类似linux的tree,不能直接用system()与exec()等函数;根据文件类型拷贝;搜索文件;删除文件等。(暂时加了这么一些功能)

8月17日补:移动、复制到的目录已包含该文件则选择覆盖或者加命名。

实现思路

  先完成基本,逐步完成扩展再优化重构代码。

实现过程

基本功能

  基于linux,通过线程池实现的。核心就是线程池的三大基本功能--线程例程、添加线程、销毁线程池。由这三个为基础,对项目进行展开。基本功能,即通过递归读取目录,通过strucr dirent *p这个结构体来实现判断文件类型。如果是普通文件,直接在新目录用文件IO的读写实现拷贝功能(包括标准IO、系统IO,还有共享内存也可以实现),拷贝那里用“添加线程”,保证可以多线程实现拷贝;如果是目录文件,就先创建文件夹--mkdir(),再sprintf拼接字符串以及函数的递归实现子级目录的拷贝。

->拷贝代码

void *myregcp(void *myarg)
{
struct copypath *mypath=(struct copypath *)myarg; //系统IO的复制
int fd1,fd2;
fd1=open(mypath->oldpath,O_RDONLY);
fd2=open(mypath->newpath,O_CREAT|O_TRUNC|O_RDWR,0777);
if(fd1==-1)
{
perror("打开1失败\n");
return NULL;
}
if(fd2==-1)
{
perror("打开2失败\n");
return NULL;
}
char buf[SIZE];
int nread,nwrite;
while(1)
{
bzero(buf,SIZE);
nread=read(fd1,buf,SIZE);
if(nread==0)
break;
cs=cs+nread;
write(fd2,buf,nread);
}
close(fd1);
close(fd2);
return NULL;
}

->递归读取全部目录

int myreaddir(struct copypath *pp,struct threadpool *pool)
{
DIR *dirp=opendir(pp->oldpath);
if(dirp==NULL)
{
perror("失败:\n");
return -1;
}
struct dirent *p;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
add_task(myregcp,mypath,pool); //实现
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
mkdir(mydirpath->newpath,0777);
myreaddir(mydirpath,pool);
}
}
}
closedir(dirp);
return 1;
}

  这样就大概完成基本功能,用多线程实现大文件夹的拷贝。

扩充功能

->进度条

  定义两个全局变量,一个用于计算总字节数,另一个计算每次复制的字节数,再用一个显示函数实现进度条的显示。这里要注意缓冲区的问题,所以我用了"fflush(NULL)"这个函数,让它每打印一个'|'的时候,就刷新一次缓冲区。计算总的字节数直接递归全部目录,用"struct stat info"这个结构体里面的"info.st_size"累加,即可得到总的字节数;拷贝功能函数里面有个"cs"变量,就是存放拷贝字节数。显示进度条就用简单的判断,加相除实现。因为是显示20个|,所以我乘20。

  num=(float)cs;        //正在复制字节数
  k=(num/s)*20;

->耗时

  有三种思路,用clock()、time()、sleep(1)等都可以实现计时,直接在拷贝前和拷贝后加赋值,然后相减,即可。起初自己是用clock()这个函数,但是每次都是三秒。。。然后转到sleep(),让它自己while()累加实现。

->代码实现树

  还是递归的思想,递归如果是普通文件就打印,是目录文件夹就字符串拼接再递归打印子文件夹下的子文件。

void dirtree(char dirpath[],int level)
{
int i;
char *dirname=NULL;
int dirlen;
DIR *dp=opendir(dirpath);
if(dp==NULL)
{
perror("失败:\n");
return;
}
struct dirent *ep;
while((ep=readdir(dp))!=NULL)
{
if(strncmp(ep->d_name, ".", 1) == 0)
continue;
for(i=0;i<level;i++)
{
printf("|");
printf(" ");
}
printf("|--- ");
printf("\033[1;32;40m %s \033[0m\n",ep->d_name);
if(ep->d_type==DT_DIR)
{
//当前目录长度
dirlen=strlen(dirpath)+1;
//备份
dirname=(char *)malloc(dirlen);
memset(dirname,0,dirlen);
memcpy(dirname,dirpath,dirlen); strcat(dirpath,"/");
strcat(dirpath,ep->d_name);
dirtree(dirpath,level+1); //递归实现树效果
//恢复之前的目录名
memcpy(dirpath,dirname,dirlen);
free(dirname);
dirname = NULL;
}
}
closedir(dp);
}

->按类型拷贝文件

  也比较简单,另建一个递归读目录的函数,在普通文件加个if条件判断就可以。

  if(strstr(p->d_name,ftype)!=NULL)

->搜索文件

  类似于win的文件检索功能,在输入那个文件下面实现相似文件名的检索,并打印相关路径。也是递归读取目录,核心的改变代码也就一句。用"strstr()"寻找相应的子字符串,打印。

  if(strstr(p->d_name,filename)!=NULL)

->删除文件夹

  删除稍微要注意一下如果文件夹下面还有其他文件,就不能直接用"rmdir"删除文件夹。先用remove()删除文件,之后再删除子文件夹。也是用递归思想实现的。

实现效果

  现在还传不了,后期再传吧。

全部代码

#include "myhead.h"
#define SIZE 1024*1024
long int s=0; //总字节数
long int cs=0; //计算每次复制的字节数
int tm=0; //计时--以秒为单位
int flag; //结束标志位
/***************************相关结构体的定义******************************/
struct copypath
{
char oldpath[256];
char newpath[256];
char target[50];
};
//创建任务链表结构体
struct tasklist
{
void *(*taskp)(void *);
void *taskarg;
struct tasklist *next;
};
//创建任务链表表头
struct tasklist *myhead;
//初始化任务链表
struct tasklist* task_init()
{
struct tasklist *mytask=malloc(sizeof(struct tasklist));
mytask->taskp=NULL;
mytask->taskarg=NULL;
mytask->next=NULL;
return mytask;
}
//创建线程池
struct threadpool
{
int threadnum;//统计当前线程数量
pthread_t *threadid;//存放当前线程的ID号
struct tasklist *taskhead;//保存任务链表的头结点
pthread_mutex_t threadmutex;//互斥锁
int tasknum;//统计任务链表中的数量
pthread_cond_t threadcond;//条件变量
bool threadflag;//用于判断线程池是否开启
}; //线程的多任务函数
void *routine(void *arg)
{
struct threadpool *pool=(struct threadpool *)arg;
//负责从任务链表的头结点的下一个位置取出任务然后处理
struct tasklist *p;
while(1)
{
//上锁
pthread_mutex_lock(&(pool->threadmutex));
//判断数量是否为0
while(pool->threadflag==true && pool->tasknum==0)
{
//printf("%ld线程阻塞--wait\n",pthread_self());
pthread_cond_wait(&(pool->threadcond),&(pool->threadmutex));
}
if(pool->threadflag==false&&pool->tasknum==0)
{
pthread_mutex_unlock(&(pool->threadmutex));
pthread_exit(NULL);
}
//取出节点处理
p=pool->taskhead->next;
pool->taskhead->next=p->next;
p->next=NULL;
//更新任务数量
pool->tasknum--;
//printf("%ld线程正在执行任务\n",pthread_self());
//解锁
pthread_mutex_unlock(&(pool->threadmutex));
(p->taskp)(p->taskarg);
free(p);
}
}
//初始化线程池结构体
struct threadpool *thread_init(int num)
{
struct threadpool *mythread=malloc(sizeof(struct threadpool));//申请堆空间
mythread->threadnum=num;
mythread->threadid=malloc(num*sizeof(pthread_t));
//初始化链表的表头
mythread->taskhead=myhead;
//锁初始化
pthread_mutex_init(&(mythread->threadmutex),NULL);
//条件变量初始化
pthread_cond_init(&(mythread->threadcond),NULL);
mythread->tasknum=0;
mythread->threadflag=true;
for(int i=0;i<num;i++)
pthread_create(&(mythread->threadid[i]),NULL,routine,mythread);
return mythread;
}
//添加任务函数
int add_task(void *(*p)(void *),void *newarg,struct threadpool *pool)
{
//找到尾部
struct tasklist *q=pool->taskhead;
while(q->next!=NULL)
q=q->next;
//准备新结点
struct tasklist *newnode=malloc(sizeof(struct tasklist));
newnode->taskp=p;
newnode->taskarg=newarg;
newnode->next=NULL; //上锁
pthread_mutex_lock(&(pool->threadmutex));
//尾插
q->next=newnode;
//更新任务数量
pool->tasknum++;
pthread_mutex_unlock(&(pool->threadmutex));
//唤醒条件
pthread_cond_signal(&(pool->threadcond));
return 0;
}
/***************************************************************************/
// 功能函数
/***************************************************************************/
//主目录名
void *mycopyname(void *myarg)
{
struct copypath *mypath=(struct copypath *)myarg;
char fpath[15]; //求出主目录的名字
char temp[100];
strcpy(temp,mypath->oldpath);
char *p=strtok(temp,"/");
//获取文件名
while(p!=NULL)
{
bzero(fpath,15);
strcpy(fpath,p);
p=strtok(NULL,"/");
}
strcpy(((struct copypath *)myarg)->target,fpath);
}
//普通文件复制
void *myregcp(void *myarg)
{
struct copypath *mypath=(struct copypath *)myarg; //系统IO的复制
int fd1,fd2;
fd1=open(mypath->oldpath,O_RDONLY);
fd2=open(mypath->newpath,O_CREAT|O_TRUNC|O_RDWR,0777);
if(fd1==-1)
{
perror("打开1失败\n");
return NULL;
}
if(fd2==-1)
{
perror("打开2失败\n");
return NULL;
}
char buf[SIZE];
int nread,nwrite;
while(1)
{
bzero(buf,SIZE);
nread=read(fd1,buf,SIZE);
//cs=cs+nread;
if(nread==0)
break;
cs=cs+nread;
write(fd2,buf,nread);
}
close(fd1);
close(fd2);
return NULL;
}
//遍历读目录
int myreaddir(struct copypath *pp,struct threadpool *pool)
{
DIR *dirp=opendir(pp->oldpath);
if(dirp==NULL)
{
perror("失败:\n");
return -1;
}
struct dirent *p;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
add_task(myregcp,mypath,pool); //实现
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
mkdir(mydirpath->newpath,0777);
myreaddir(mydirpath,pool);
}
}
}
closedir(dirp);
return 1;
}
//递归算字节数
int size_sum(struct copypath *pp)
{
DIR *dirp=opendir(pp->oldpath);
if(dirp==NULL)
{
perror("失败:\n");
return -1;
}
struct dirent *p;
struct stat info;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
//计算字节数
stat(mypath->oldpath,&info);
s=s+info.st_size;
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
size_sum(mydirpath);
}
}
}
closedir(dirp);
return 1;
}
//实现进度条
void *pro_bar(void *myarg)
{
int i,j=0;
float k,num;
printf("进度:");
while(1)
{
j=k;
num=(float)cs; //正在复制字节数
k=(num/s)*20; //
k=(int)k;
if(k-j>=1)
{
for(i=0;i<k-j;i++)
{
printf("\033[1;31;42m | \033[0m");
}
fflush(NULL);
}
usleep(10000);
if(s==cs)
{
printf("\033[1;31;42m | \033[0m");
fflush(NULL);
usleep(200);
break;
}
}
printf("\n任务完成\n");
return NULL;
}
//lseep计时
void *my_time(void *myarg)
{
while(1)
{
sleep(1);
tm++;
if(s==cs)
{
break;
}
}
}
//显示选择拷贝类型界面
int showdow()
{
int n;
printf("**********************\n");
printf(" 请输入你要拷贝的文件 \n");
printf(" 1.复制全部文件; \n");
printf(" 2.选择类型复制; \n");
printf(" 3.原目录文件树; \n");
printf(" 4.查找某个文件; \n");
printf(" 5.删除某个文件. \n");
printf("**********************\n");
scanf("%d",&n);
return n;
}
//递归读取文件类型的字节数
int ftypesize_sum(struct copypath *pp,char *ftype)
{
DIR *dirp=opendir(pp->oldpath);
if(dirp==NULL)
{
perror("失败:\n");
return -1;
}
struct dirent *p;
struct stat info;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
if(strstr(p->d_name,ftype)!=NULL) //文件类型
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
//计算字节数
stat(mypath->oldpath,&info);
s=s+info.st_size;
}
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
ftypesize_sum(mydirpath,ftype);
}
}
}
closedir(dirp);
return 1;
}
//递归读取文件类型的目录
int myftyper(struct copypath *pp,struct threadpool *pool,char *ftype)
{
DIR *dirp=opendir(pp->oldpath);
if(dirp==NULL)
{
perror("失败:\n");
return -1;
}
struct dirent *p;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
if(strstr(p->d_name,ftype)!=NULL)
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
add_task(myregcp,mypath,pool); //实现
}
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
mkdir(mydirpath->newpath,0777);
myftyper(mydirpath,pool,ftype);
}
}
}
closedir(dirp);
return 1;
}
//树实现
void dirtree(char dirpath[],int level)
{
int i;
char *dirname=NULL;
int dirlen;
DIR *dp=opendir(dirpath);
if(dp==NULL)
{
perror("失败:\n");
return;
}
struct dirent *ep;
while((ep=readdir(dp))!=NULL)
{
if(strncmp(ep->d_name, ".", 1) == 0)
continue;
for(i=0;i<level;i++)
{
printf("|");
printf(" ");
}
printf("|--- ");
printf("\033[1;32;40m %s \033[0m\n",ep->d_name);
if(ep->d_type==DT_DIR)
{
//当前目录长度
dirlen=strlen(dirpath)+1;
//备份
dirname=(char *)malloc(dirlen);
memset(dirname,0,dirlen);
memcpy(dirname,dirpath,dirlen); strcat(dirpath,"/");
strcat(dirpath,ep->d_name);
dirtree(dirpath,level+1); //递归实现树效果
//恢复之前的目录名
memcpy(dirpath,dirname,dirlen);
free(dirname);
dirname = NULL;
}
}
closedir(dp);
} //递归查找相似文件-查找文件
int sc_file(struct copypath *pp,char *filename)
{
DIR *dirp=opendir(pp->oldpath);
if(dirp==NULL)
{
perror("失败:\n");
return -1;
}
struct dirent *p;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
if(strstr(p->d_name,filename)!=NULL) //文件类型
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
printf("已找到文件路径:%s\n",mypath->oldpath);
free(mypath);
}
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
if(strstr(p->d_name,filename)!=NULL) //文件类型
{
struct copypath *mypath1=malloc(sizeof(struct copypath));
sprintf(mypath1->oldpath,"%s/%s",pp->oldpath,p->d_name);
printf("已找到文件路径:%s\n",mypath1->oldpath);
free(mypath1);
}
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
sc_file(mydirpath,filename);
}
}
}
closedir(dirp);
return 1;
}
//删除--文件\文件夹
int alldet(struct copypath *pp)
{
DIR *dirp=opendir(pp->oldpath);
struct dirent *p;
while((p=readdir(dirp))!=NULL)
{
if(p->d_type==DT_REG) //普通文件
{
struct copypath *mypath=malloc(sizeof(struct copypath));
sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
remove(mypath->oldpath);
}
if(p->d_type==DT_DIR) //文件夹
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
struct copypath *mydirpath=malloc(sizeof(struct copypath));
sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
alldet(mydirpath);
rmdir(mydirpath->oldpath);
}
}
}
closedir(dirp);
rmdir((pp->oldpath));
return 1;
}
/***************************************************************************/ /***************************************************************************/
// 简化主程序
/***************************************************************************/
int simcopy_all(struct threadpool *mypool) //简化主程序--复制全部
{
tm=s=cs=0;
struct copypath paths; //新旧路径结构体
printf("请输入源文件\n");
scanf("%s",paths.oldpath);
printf("请输入目标文件\n");
scanf("%s",paths.newpath);
mycopyname(&paths);
sprintf(paths.newpath,"%s/%s",paths.newpath,paths.target);
mkdir(paths.newpath,0777);
size_sum(&paths); //计算字节数
usleep(20);
printf("总字节数:%ld\n",s);
add_task(my_time,NULL,mypool);
add_task(pro_bar,NULL,mypool);
myreaddir(&paths,mypool);
}
void simcopy(struct threadpool *mypool) //简化主程序--按文件类型复制
{
tm=s=cs=0;
char ftype[6]; //文件类型变量
struct copypath paths;
printf("请输入源文件\n");
scanf("%s",paths.oldpath);
printf("请输入目标文件\n");
scanf("%s",paths.newpath);
mycopyname(&paths);
sprintf(paths.newpath,"%s/%s",paths.newpath,paths.target);
mkdir(paths.newpath,0777);
printf("请输入要复制的文件类型,如.txt等\n");
scanf("%s",ftype);
ftypesize_sum(&paths,ftype);
printf("总字节数:%ld\n",s);
usleep(20);
add_task(my_time,NULL,mypool);
add_task(pro_bar,NULL,mypool);
myftyper(&paths,mypool,ftype);
}
void simtree() //简化主程序--文件树
{
char direntName[256];
struct copypath paths;
printf("请输入源文件\n");
scanf("%s",paths.oldpath);
memset(direntName, 0, sizeof(direntName));
strcat(direntName, paths.oldpath);
printf("%s\n",paths.oldpath);
dirtree(direntName, 0);
}
void myscfile() //简化主程序--查找
{
char fname[256];
struct copypath paths;
printf("请输入查找文件夹名\n");
scanf("%s",paths.oldpath);
printf("请输入要查找的文件名\n");
scanf("%s",fname);
sc_file(&paths,fname);
usleep(10);
}
void mydel() //简化主程序--删除
{
tm=s=cs=0;
char delfile[100];
struct copypath paths;
printf("请输入要删除的文件夹\n");
scanf("%s",paths.oldpath);
size_sum(&paths); //计算字节数
printf("size is: %ld\n",s);
alldet(&paths);
usleep(10);
}
void endshow() //简化主程序--结束
{
printf("请输入 \n");
printf(" 1--继续 \n");
printf(" 2--退出 \n");
scanf("%d",&flag);
}
/***************************************************************************/
//销毁线程池
int pool_destroy(struct threadpool *pool)
{
int i;
//改变标志位,让线程退出死循环
pool->threadflag=false;
//唤醒所有线程
pthread_cond_broadcast(&(pool->threadcond));
//回收所有线程
for(i=0;i<pool->threadnum;i++)
{
pthread_join(pool->threadid[i],NULL);
//printf("%ld线程已被回收\n",pool->threadid[i]);
}
return 0;
} int main()
{
struct copypath paths;
while(1)
{
flag=0;
system("clear");
myhead=task_init(); //初始化任务链表的表头
struct threadpool *mypool=thread_init(10); //创建并初始化线程池
int ret=showdow();
switch(ret)
{
case 1: //拷贝全部
simcopy_all(mypool);
pool_destroy(mypool); //线程池的销毁
printf("拷贝花费:%d seconds\n",tm);
break;
case 2: //拷贝部分
simcopy(mypool);
pool_destroy(mypool);
printf("拷贝花费:%d seconds\n",tm);
break;
case 3: //显示文件树
simtree();
break;
case 4: //查找某个文件--显示相似的文件
myscfile();
break;
case 5: //删除某个文件夹
mydel();
printf("delete done\n");
break;
default:
break;
}
endshow();
if(flag==1)
continue;
else if(flag==2)
break;
}
system("clear");
usleep(20);
return 0;
}

码源:

http://pan-yz.chaoxing.com/share/info/b54be58ad063e1e9

有什么建议,欢迎联系。邮箱:2460576606@qq.com

基于linux与线程池实现文件管理的更多相关文章

  1. 开源项目SMSS开发指南(二)——基于libevent的线程池

    libevent是一套轻量级的网络库,基于事件驱动开发.能够实现多线程的多路复用和注册事件响应.本文将介绍libevent的基本功能以及如何利用libevent开发一个线程池. 一. 使用指南 监听服 ...

  2. linux C 线程池(物不可穷也~)

    Linux 多线程编程之 线程池 的原理和一个简单的C实现,提高对多线程编 程的认知,同步处理等操作,以及如何在实际项目中高效的利用多线程开 发. 1.  线程池介绍 为什么需要线程池??? 目前的大 ...

  3. Linux pthread 线程池实现

    基于pthread封装了一个简易的ThreadPool,具有以下特性: 1.具有优先级的任务队列 2.线程池大小可以二次调整,增加线程或者删除空闲线程 3.任务两种重写方式,重写run或者使用函数回调 ...

  4. Linux C++线程池实例

    想做一个多线程服务器测试程序,因此参考了github的一些实例,然后自己动手写了类似的代码来加深理解. 目前了解的线程池实现有2种思路: 第一种: 主进程创建一定数量的线程,并将其全部挂起,此时线程状 ...

  5. 基于hystrix的线程池隔离

    hystrix进行资源隔离,其实是提供了一个抽象,叫做command,就是说,你如果要把对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内 对这个依赖服务的所有调用请求,全部走这个资源池内的资源 ...

  6. Linux C++线程池

    .为什么需要线程池? 部分应用程序需要执行很多细小的任务,对于每个任务都创建一个线程来完成,任务完成后销毁线程,而这就会产生一个问题:当执行的任务所需要的时间T1小于等于创建线程时间T2和销毁线程时间 ...

  7. Linux下线程池的理解与简单实现

    首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...

  8. 基于C++11线程池

    1.包装线程对象 class task : public std::tr1::enable_shared_from_this<task> { public: task():exit_(fa ...

  9. Linux简单线程池实现(带源码)

    这里给个线程池的实现代码,里面带有个应用小例子,方便学习使用,代码 GCC 编译可用.参照代码看下面介绍的线程池原理跟容易接受,百度云下载链接: http://pan.baidu.com/s/1i3z ...

随机推荐

  1. 踩坑系列《九》 无法获取实体类xxx对应的表名

    话不多说,直接说明原因 类似于 @MapperScan(basePackages = "com.hyxiao.user.mapper") 启动类的mapper扫描注解的导入包正确的 ...

  2. 开源框架 - 新 代码生成器 WebFirst / .NET Core

    框架描述 WebFirst  是一新代的 代码生成器,用法简单,功能强大,支持多种数据库 ,具体功能如下: 一. 建库.CodeFirst方式在线建表,没用到CodeFirst的用户可以用工具轻松体验 ...

  3. 从源码解析Electron的安装为什么这么慢

    前言 Electron作为一款跨平台的桌面应用端解决方案已经风靡全球.作为开发者,我们几乎不用关心与操作系统的交互,直接通过Web前端技术与Electron提供的API就可以完成桌面应用端的开发. 然 ...

  4. wqs二分 学习笔记

    wqs二分学习笔记 wqs二分适用题目及理论分析 wqs二分可以用来解决这类题目: 给你一个强制要求,例如必须\(n\)条白边,或者划分成\(n\)段之类的,然后让你求出最大(小)值.但是需要满足图像 ...

  5. 洛谷3288 SCOI2014方伯伯运椰子(分数规划+spfa)

    纪念博客又一次爆炸了 首先,对于本题中,我们可以发现,保证存在正整数解,就表示一定费用会降低.又因为一旦加大的流量,费用一定会变大,所以总流量一定是不变的 那么我们这时候就需要考虑一个退流的过程 对于 ...

  6. FastAPI 学习之路(二)

    之前的文章已经介绍了如何安装,以及简单的使用,这篇文章呢,我们就不去分享如何安装对应的包了. 我们如何去编写呢,其实很简单,按照下面的步骤,一个简单的基于fastapi的接口就编写完毕. 首先:创建一 ...

  7. SudokuSolver 1.0:用C++实现的数独解题程序 【一】

    SudokuSolver 1.0 用法与实现效果 SudokuSolver 是一个提供命令交互的命令行程序,提供的命令清单有: H:\Read\num\Release>sudoku.exe Or ...

  8. python在指定一行的下一行插入文本

    给定一个程序,程序中有许多函数,比如,funcA,funcB,现在,如何在生成的函数中插入一个logger()语句? 这里用一个solidity程序做例子 pragma solidity ^0.4.0 ...

  9. react 生命周期 个人见解

    初始化/实例期 gitDefaultprops 获取组件的默认props状态 gitInitialstate 类定义方式或是直接在构造函数中挂载state componentWillMount  组件 ...

  10. USART波特率 vs SPI速率--学习笔记

    本篇文章将与大家探讨USART波特率 vs SPI速率.这里提出一个问题,为什么USART的波特率是内核时钟的1/8或者1/16,而SPI最快的频率可以是内核时钟的1/2. 请大家带着这个问题来阅读本 ...