多线程序:
背景:计划用多线程往数据库插入两百万数据,查看耗时多久。以及不用线程,和用不同线程数,执行时间分别是多少。以达到对线程提升程序效率的认识。
计划分别测试三项,不用线程,用和处理器一样的线程数,以及用超过处理器数的线程。即一个线程,4线程(本电脑是4核八处理器),10线程
for(String key : listMap.keySet()) { List<PackCode> temp = listMap.get(key); new Thread(()->{ System.out.println("当前线程"+Thread.currentThread().getName()+"----"+key); temp.forEach(i->testRepository.saveAndFlush(i)); long end = System.currentTimeMillis()/1000; System.out.println("线程"+Thread.currentThread().getName()+"----"+key+"执行完耗时(s)"+ (end-begin)); }).start();
如上,为第一版,会报很多线程错误,怀疑是不同线程资源访问冲突。虽然报错,但是还是在往数据库插入数据。修改为加同步synchronized方法的方式
for(String key : listMap.keySet()) { List<PackCode> temp = listMap.get(key); new Thread(()->{ System.out.println("当前线程"+Thread.currentThread().getName()+"----"+key); synchronized (this){ temp.forEach(i->testRepository.saveAndFlush(i)); } long end = System.currentTimeMillis()/1000; System.out.println("线程"+Thread.currentThread().getName()+"----"+key+"执行完耗时(s)"+ (end-begin)); }).start();
此时不再报错,执行时间和上面一段代码时间大体一致。
十个线程数测试
测试过程中,加了同步关键字后,发现实际是一个线程执行完以后,另一个线程才能继续,实际上还是相当于单线程一样的结果,未达到并行的效果。一个十个线程,每个线程插入20w,运行时间如下
线程Thread-74----1执行完耗时(s)349
线程Thread-83----10执行完耗时(s)684
线程Thread-82----9执行完耗时(s)1066
4个线程数测试
线程Thread-72----2执行完耗时(s)943
线程Thread-74----4执行完耗时(s)1922
线程Thread-71----1执行完耗时(s)2744
线程Thread-73----3执行完耗时(s)3561
4个线程执行200w,每个是50w,效果是一样的,这样,先执行完一个线程,再执行下一个线程,没有做到并行。这里可以对比下,4个线程执行和10个线程执行时间基本一样,因为都是先执行完一个线程,再执行另一个线程。
单进程
如果只用一个主线程跑,还是和多线程有点区别的,特别慢,所以单线程插入20w,时间更长。
由于20w条太久,这里只看同样跑6分钟,能插入多少条
数据出来了,只插入7k多条,跟用多线程的效果相差很大。
表里建索引,插入时间缩短。原来一个索引,插入50w用时943s,再加一个主键id索引,用时875s
再加索引,提升时间效果就不大了,时间反而会有所增长