定时器每1分钟接收一次文件, 接收后写入文件队列, 然后唤醒文件线程
文件线程查看文件队列, 有文件就一直处理文件, 文件队列为空就wait()
处理文件分为subscribesubscription-update两种情况
处理文件, 即唤醒处理数据线程管理器, 处理数据线程管理器再把切割(100k一个小文件)的文件按顺序分别唤醒10 处理数据线程去处理
如果是subscribe, 由于数据全部都是insert, 所以可以10个线程并行处理的时候, 可以不考虑SQL数据的顺序处理, 直接处理到数据库就行了
如果是subscription-update, 由于数据可以先更新为a, 再更新为b, 所以SQL的处理必须按顺序, 即唤醒处理数据线程管理器, 处理数据线程管理器第一寻找可用的线程(即该线程目前处于wait状态)第二寻找可用的SQL临时存储队列(共分配了10二维数组), 两者都找到可用, 则指定该线程处理当前切割后的小文件, 并将SQL语句存后SQL临时存储队列, 同时通知SQL执行线程哪个二维数组已经有完整数据了
SQL执行线程按顺序查看是否有已经有完整数据的二维数组, 有的就进行处理
各线程什么时候waitnotify:
定时器接收完文件, notify文件线程
文件线程发现文件队列为空, wait
文件之间(非切割的小文件之间)处理不可并行, 所以文件线程只采用一个, 处理数据线程管理器也只能采用一个, 并给后者加synchronized同步(这样如果文件线程遇到两个文件, 第二次notify管理器后, 会阻塞, 直到第一个文件处理完, 这样是对的, 但如果此时被定时器notify会出乱? 在管理器上加一正在处理标志, 不凭本身线程状态来判断或阻塞, 这样一个时刻处理数据线程管理器只会处理一个文件)
依上方法, 处理数据线程管理器执行完自己wait
同时, 处理数据线程管理器处理完后立即notify文件线程, 这样对有积压多个文件的时候有好处, 不必等待定时器notify
文件线程发现文件, 正在处理标志为否, notify处理数据线程管理器
SQL执行线程有按顺序的二维数组, 则一直按顺序处理, 没有就wait()
每次处理数据线程处理完就notifySQL执行线程(适用于subscription-update)




通过以上 切割文件 和 多线程 的方案, 同时连接池保持10个数据库连接, 使速度提高了6倍左右, 在本地测试时一分钟处理4M的数据
再优化mysql参数, 又提高了8倍左右, 核心的是innodb_flush_log_at_trx_commit, 是一秒钟写一次事务日志, 还是每个SQL写一次事务日志(如果一秒执行400个SQL,后者模式需要1秒写400次磁盘, 很影响效率), 现在在本地测试(双核5000+, 2G内存)达到一分钟处理35M的数据, CPU平均占用95%