作者tnsshnews (tnsshnews)
看板java
标题Re: [问题] Java Multithreading Writ/Read/Create
时间Tue Oct 23 12:14:39 2012
谢谢大大的分享, 小弟目前已经几乎要完成了,
但遇到一个问题, 就是当BlockingQueue里面的东西都被取光,
就会一直block在那边, thread2就不会结束, 一直hold在那边,
也没有办法判断时间是不是超过五分钟, 要换档!!
※ 引述《adrianshum (Alien)》之铭言:
: ※ 引述《tnsshnews (tnsshnews)》之铭言:
: : Dear all,
: : 小弟为Multithreading新手一位, 过去鲜少写过多执行序的问题。
: : 目前程式执行需要三个执行序:
: : Thread-1: 持续监听网路封包
: : Thread-2: 一有新封包接收到, 立刻写入档案
: : Thread-3: 每隔五分钟产生一个新档案(.bak), 任何新收到的封包,写入最
: : 产生的档案里,
: : 等一个五分钟的新档案产生之後, 上一个档案的.bak便取消掉
: : (.bak的目的是确保该档案目前还未关闭)
: 这样做不是不可以,只是个人觉得这三个动作未至於独立到要分开
: thread做,单 thread 就可以写得很有条理了。anyway, 後面继续
: : 小弟目前做法是:
: : Thread-1: 每个几秒钟, 就询问server, 是否有新封包, 如果有, 便一直塞入List中
: : Thread-2: 利用loop一直扫描Thread-1的List, BufferWriter写入档案, 并将以写入
: : 档案的资料从List删除(确保List中资料都是未写入档案的)
: 建议避免这样做 polling.
: Java 本身就有现成好用的 producer-consumer queue (BlockingQueue)
: : Thread-3: 每隔五分钟产生新档案(.bak), 并将五分钟内接收的新资料写入该档案,
: : 下一个五分钟产生新档案时, 将上一个五分钟产生的档案改档名
: : (取消.bak), 关闭BufferWriter指向,
: : 并将Thread-2的BufferWriter指向新的档案(新的.bak)
: : 目前已经完成差不多, 但测试时发现多问题
: : 1. 如果一边有新资料进来, 一边又写入档案, 会不会造成非同步呢?
: : 目前我是将写过的资料, 从List删除, 这样可确保留在List的资料都是尚未写入的,
: : 但总觉得这样写很不漂亮!!
: 改用 blocking queue,效果就是:
: Thread 1 一直写入新的 item
: Thread 2 一直从 queue 取得新的 item 写进档案。
: 看起来就整洁许多。
: 用 List 也差不多,只是你要小心 synchronize 的问题。
: 直接用 ArrayList你会死很惨
: : 2. 因为每五分钟换一次档案, 所以写档案的Thread, 不会关掉BufferWriter,
: : 但没关掉
: : 就不能改档名。目前机制是, 还没有换档前, 档案一直会有新资料写进来,
: : 因为产生的档案是要给另一只程式读的, 为了避免另一只程式不会读到不
: : 完整的资料,
: : 所以采取这样的手法, 但也觉得这样不够漂亮@@
: : 感激不尽!!
: 最基本的改法是加入适当的 synchronization control.
: 在写档时,改档案的 thread 就乖乖等;改档案时,就轮写档的
: thread 在等。
: 由於 Writer 或会丢弃,直接 synchronize writer 未必太适合,
: 可以弄一个 semaphore,或弄一个 dummy obj 作 mutex, 然後
: 写档前及改档前就 lock
: 更进一步,为了让程式更好维护,不妨把这部份包得好看一点,比如:
: class DataItemOutput {
: private Writer writer;
: publc synchronized void writeItem(DataItem item) {
: writer.write(item.toString());
: }
: public synchronized void rollFile() {
: writer.close();
: // .... 开新 writer, 删旧档 etc
: }
: }
: 这样 thread 2 & 3 都变得很简单:
: Thread2:
: while (!end) {
: DataItem item = dataItemQueue.take();
: dataItemOutput.writeItem(item);
: }
: Thread3:
: while (!end) {
: sleep(5 minutes);
: dataItemOutput.rollFile();
: }
: 再更一步,Thread3 可以用 TimerTask, ScheduledExecutorService 之类
: 然後再更进一步,你会发觉 roll file 的 thread 其实是多余的。
: 只要你在 DataItemOutput.writeItem() 里,检查一下现在的 file
: 是什麽时候开,这五分钟就开新并纪绿新时间,Thread3 根本就没有
: 存在必要了:
: class DataItemOutput {
: private Writer writer;
: private Date fileTime;
: publc void writeItem(DataItem item) {
: if (currentTime > fileTime + 5minutes) {
: rollFile();
: }
: writer.write(item.toString());
: }
: public void rollFile() {
: writer.close();
: // .... 开新 writer, 删旧档 etc
: fileTime = currentTime;
: }
: }
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 203.79.199.63
1F:→ n3oanderson:send a msg signifying the end of the queue; then 10/23 22:20