发表于: 2017-09-05 23:33:59
3 925
先简单说一说多线程:
1.多线程有两种实现方式:
首先是线程类:a.用一个类去继承Thread类,b.用一个类去实现Runnable接口,二者都需要复写public void run()方法。
然后是线程的创建:在需要创建线程的地方,a.创建线程类对象,b.创建Thread类对象并传入线程类对象作为参数。
最后是线程的启动:用上一步创建的线程对象的start方法启动线程:t.start()。
二者的区别就是,a可以复写Thread类中的更多方法,来实现更高深的功能;b由于是实现接口,不影响其继承体系。实际使用中,绝大部分情况下用b。
我的程序中也是用的b方法,对照着看应该很容易看明白。。
2.多线程的运行
由CPU自动分配各线程的切换,虽然可以设置线程的优先级,但用处不大。。
真要调控线程的运行,最简单的方法是用wait()/sleep()让线程挂起,用notify()唤醒wait中的线程,sleep中的线程只能时间到了自己醒。不过sleep任何时候都能用,wait/notify仅在同步中使用。
另外还可以调用一个线程的join()方法,令其优先运行。比如在a线程中调用b.join(),则a挂起,直到b运行结束,再继续运行a。
优化2:通过多线程,同时执行多个生成数据并插入的操作(代码链接)
将优化1后的代码放入线程类的run方法中,然后在主函数中创建10个线程类并运行。
结果:效率明显提升,多个连接传输速度要快很多。
插入100万条数据耗时:461秒(5个线程)、316秒(10个线程)。(单线程时间:1700秒左右)
中途出现过的bug:
多线程执行生成随即数据然后插入数据库的操作,5个线程正常,10个线程就会卡死
最开始以为是数据库连接池最大连接数的问题,然而最大连接数改到20还是会这样。
原因1:因为加了线程,原先需要双循环的程序改成单循环了,于是变成了10个线程都是一次性插入10W条数据到数据库中,此时内存中要产生10个装了10W条数据的集合,内存会溢出。而在内存溢出之前,一次性提交10个10W条数据的批处理到数据库中,在批处理执行和垃圾回收之间可能产生了冲突。
发现了内存溢出后,修改代码为每个线程中单次产生1W条数据,循环10次。然而问题依旧在。
原因2:修改时一时疏忽,把创建List和插入数据库的代码和放在了循环外,这就是说,程序依然会在list中存入10W条数据然后一次性插入数据库,后面的事就和上面一样了。
解决:将创建List和插入数据库的代码和放在外层循环中,就好了。
这个bug卡了我一整晚,一点点Debug,看底层源代码,找程序是卡在哪里了→_→粗心大意简直要命
评论