您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 招标投标 > JAVA中用多线程技术实现大数据导入
JAVA中用多线程技术实现大数据导入朋友让我帮忙写个程序从文本文档中导入数据到oracle数据库中,技术上没有什么难度,文档的格式都是固定的只要对应数据库中的字段解析就行了,关键在于性能。数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis()在最后一个子进程结束后记录当前时间,两次一减得到的时间差即为总共的用时,代码如下Java代码longtStart=System.currentTimeMillis();System.out.println(Thread.currentThread().getName()+开始);//打印开始标记for(intii=0;ii<threadNum;ii++){//开threadNum个线程Runnabler=newRunnable(){@Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName()+开始);//做一些事情......System.out.println(Thread.currentThread().getName()+结束.);}}Threadt=newThread(r);t.start();}System.out.println(Thread.currentThread().getName()+结束.);//打印结束标记longtEnd=System.currentTimeMillis();System.out.println(总共用时:+(tEnd-tStart)+millions);longtStart=System.currentTimeMillis();System.out.println(Thread.currentThread().getName()+开始);//打印开始标记for(intii=0;ii<threadNum;ii++){//开threadNum个线程Runnabler=newRunnable(){@Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName()+开始);//做一些事情......System.out.println(Thread.currentThread().getName()+结束.);}}Threadt=newThread(r);t.start();}System.out.println(Thread.currentThread().getName()+结束.);//打印结束标记longtEnd=System.currentTimeMillis();System.out.println(总共用时:+(tEnd-tStart)+millions);结果是几乎在for循环结束的瞬间就执行了主线程打印总共用时的语句,原因是所有的子线程是并发执行的,它们运行时主线程也在运行,这就引出了一个问题即本文标题如何让主线程等待所有子线程执行完毕。试过在每个子线程开始后加上t.join(),结果是所有线程都顺序执行,这就失去了并发的意义了,显然不是我想要的。网上Google了很久也没有找到解决方案,难道就没有人遇到过这种需求吗?还是这个问题太简单了?无耐只得自己想办法了...最后我的解决办法是,自定义一个ImportThread类继承自java.lang.Thread,重载run()方法,用一个List属性保存所有产生的线程,这样只要判断这个List是否为空就知道还有没有子线程没有执行完了,类代码如下:Java代码publicclassImportThreadextendsThread{privatestaticList<Thread>runningThreads=newArrayList<Thread>();publicImportThread(){}@Overridepublicvoidrun(){regist(this);//线程开始时注册System.out.println(Thread.currentThread().getName()+开始...);//打印开始标记//做一些事情......unRegist(this);//线程结束时取消注册System.out.println(Thread.currentThread().getName()+结束.);//打印结束标记}publicvoidregist(Threadt){synchronized(runningThreads){runningThreads.add(t);}}publicvoidunRegist(Threadt){synchronized(runningThreads){runningThreads.remove(t);}}publicstaticbooleanhasThreadRunning(){return(runningThreads.size()>0);//通过判断runningThreads是否为空就能知道是否还有线程未执行完}}publicclassImportThreadextendsThread{privatestaticList<Thread>runningThreads=newArrayList<Thread>();publicImportThread(){}@Overridepublicvoidrun(){regist(this);//线程开始时注册System.out.println(Thread.currentThread().getName()+开始...);//打印开始标记//做一些事情......unRegist(this);//线程结束时取消注册System.out.println(Thread.currentThread().getName()+结束.);//打印结束标记}publicvoidregist(Threadt){synchronized(runningThreads){runningThreads.add(t);}}publicvoidunRegist(Threadt){synchronized(runningThreads){runningThreads.remove(t);}}publicstaticbooleanhasThreadRunning(){return(runningThreads.size()>0);//通过判断runningThreads是否为空就能知道是否还有线程未执行完}}主线程中代码:Java代码longtStart=System.currentTimeMillis();System.out.println(Thread.currentThread().getName()+开始);//打印开始标记for(intii=0;ii<threadNum;ii++){//开threadNum个线程Threadt=newImportThread();t.start();}while(true){//等待所有子线程执行完if(!ImportThread.hasThreadRunning()){break;}Thread.sleep(500);}System.out.println(Thread.currentThread().getName()+结束.);//打印结束标记longtEnd=System.currentTimeMillis();System.out.println(总共用时:+(tEnd-tStart)+millions);longtStart=System.currentTimeMillis();System.out.println(Thread.currentThread().getName()+开始);//打印开始标记for(intii=0;ii<threadNum;ii++){//开threadNum个线程Threadt=newImportThread();t.start();}while(true){//等待所有子线程执行完if(!ImportThread.hasThreadRunning()){break;}Thread.sleep(500);}System.out.println(Thread.currentThread().getName()+结束.);//打印结束标记longtEnd=System.currentTimeMillis();System.out.println(总共用时:+(tEnd-tStart)+millions);打印的结果是:main开始Thread-1开始...Thread-5开始...Thread-0开始...Thread-2开始...Thread-3开始...Thread-4开始...Thread-5结束.Thread-4结束.Thread-2结束.Thread-0结束.Thread-3结束.Thread-1结束.main结束.总共用时:20860millions可以看到main线程是等所有子线程全部执行完后才开始执行的。==================================================以下为第二次编辑===============================================上面的方法有一个隐患:如果线程1开始并且结束了,而其他线程还没有开始此时runningThreads的size也为0,主线程会以为所有线程都执行完了。解决办法是用一个非简单类型的计数器来取代List型的runningThreads,并且在线程创建之前就应该设定好计数器的值。MyCountDown类Java代码publicclassMyCountDown{privateintcount;publicMyCountDown(intcount){this.count=count;}publicsynchronizedvoidcountDown(){count--;}publicsynchronizedbooleanhasNext(){return(count>0);}publicintgetCount(){returncount;}publicvoidsetCount(intcount){this.count=count;}}publicclassMyCountDown{privateintcount;publicMyCountDown(intcount){this.count=count;}publicsynchronizedvoidcountDown(){count--;}publicsynchronizedbooleanhasNext(){return(count>0);}publicintgetCount(){returncount;}publicvoidsetCount(intcount){this.count=count;}}ImportThread类Java代码publicclassImportThreadextendsThread{privateMyCountDownc;publicImportThread(MyCountDownc){this.c=c;}@Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName()+开始...);//打印开始标记//Dosomethingc.countDown();//计时器减1System.out.println(Thread.currentThread().
本文标题:JAVA中用多线程技术实现大数据导入
链接地址:https://www.777doc.com/doc-4304247 .html