发表于: 2017-09-05 23:33:59

3 924


先简单说一说多线程:

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,看底层源代码,找程序是卡在哪里了→_→粗心大意简直要命


返回列表 返回列表
评论

    分享到