Java 如何同时将数据读写到同一文件中

Java 如何同时将数据读写到同一文件中,java,multithreading,java-me,midp,Java,Multithreading,Java Me,Midp,我读过很多帖子,在这些帖子中,他们谈到了如何使用JavaME同时读写文件,而不是。我有一个特殊的用例场景,在这个场景中,我的日志文件(可能是完整的文件,也可能只是文件的一部分)定期上传到服务器。这必须在不妨碍应用程序在此同一文件中的当前日志记录的情况下继续 代码示例位于以下位置: boolean writing = true; boolean reading = true; void main() { new Thread("THREAD-FILE-READ") { pu

我读过很多帖子,在这些帖子中,他们谈到了如何使用JavaME同时读写文件,而不是。我有一个特殊的用例场景,在这个场景中,我的日志文件(可能是完整的文件,也可能只是文件的一部分)定期上传到服务器。这必须在不妨碍应用程序在此同一文件中的当前日志记录的情况下继续

代码示例位于以下位置:

boolean writing = true;
boolean reading = true;
void main() {
    new Thread("THREAD-FILE-READ") {
        public void run() {
            InputStream instream = getFileInStream();
            if (null != instream) {
                while (reading) {
                    try {
                        try {
                            synchronized(READ_LOCK) {
                                READ_LOCK.wait();
                            }
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }

                        if (writtenCharsLen > 0) {
                            byte[] bytes = new byte[writtenCharsLen];
                            instream.read(bytes, 0, writtenCharsLen);
                            System.out.println("Read="+new String(bytes));
                            bytes = null;
                            writtenCharsLen = 0;
                        }
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }
                }
            }
            closeStream(instream);
        }
    }.start();

    new Thread("THREAD-FILE-WRITE") {
        public void run() {
            OutputStream outstream = getFileOutStream();
            if (null != outstream) {
                while (writing) {
                    try {
                        byte[] str = randomString();
                        if (null != str) {
                            writtenCharsLen = str.length;
                            System.out.println("Write=" + new String(str));
                            outstream.write(str);
                            str = null;
                        }
                    } catch (IOException ex) {
                        ex.printStackTrace();

                    } finally {
                        notifyReadStream();
                    }

                    try {
                        synchronized(WRITE_LOCK) {
                            WRITE_LOCK.wait();
                        }
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
            closeStream(outstream );
        }
    }.start();

}

void notifyReadStream() {
    try {
        synchronized (READ_LOCK) {
            READ_LOCK.notify();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

void notifyWriteStream() {
    try {
        synchronized (WRITE_LOCK) {
            WRITE_LOCK.notify();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
在上面的代码中,我将用对网络IO方法的正确调用替换sop read和sop write

PS:由于这段代码将运行多个文件和多个设备,我需要尽可能压缩修改,以尽可能降低运行时堆。此外,这段代码将一直运行到应用程序生命周期,因此不考虑在中间关闭和打开文件

显示不希望出现的结果: 读写线程显示正在运行的读写sop。读取线程正在从写入线程已写入的位置读取。我在这段代码中没有遇到任何异常,但结果是不希望的。我也尝试过同步读写流,但这会引发
IllegalMonitorStateException

预期结果: 流的读取必须在写入流完成后触发,并且读取线程必须能够从文件中的任何位置读取

有什么有用的帮助/提示吗


编辑:我能够使用不同的监视器同步读写流,但我仍然觉得,使用单个监视器可以做得更好。我以后会试试的

您的第一个问题是在写入数据之前设置writenCharslen。如果您的读线程在写线程实际写入它之前看到它是非零的,那么您就有问题了。写入后移动writenCharslen=str.length


我在您的示例中看到的另一个问题是线程永远不会产生控制。它们将占用大量CPU。

我将解决此问题:

显示不需要的结果:读写线程显示正在运行用于读写的sop。读取线程正在从写入线程已写入的位置读取。我在这段代码中没有遇到任何异常,但结果是不希望的。我也尝试过同步读写流,但这会引发
IllegalMonitorStateException

如果您使用监视器同步了访问,即读卡器调用
someObject.wait()
,而写卡器调用
someObject.notify()
,请记住,您必须将这些调用包装在
someObject
上的同步块中:

synchronized(someObject) {
    someObject.wait();
}


synchronized(someObject) {
    someObject.notify();
}

这就是非法监视状态异常的原因

谢谢您的输入!但是在写入流之后移动
writeCharsLen…
并不能解决OP问题,因为它仍然是一个异步读取流。接下来,线程不能让步,因为这是一个从文件读取/写入文件的持续过程,最终将与服务器接口以上载数据。感谢您的回复!使用这种方法,我不能在这些线程中等待同一个监视器。是的,我已经同步了我的监视器,这就是为什么它抛出
IllegalMonitorStateException
,因为我需要等待写入线程上的下一次写入,并等待读取线程中的下一次读取。现在,我正在为每个线程设置单独的监视器,它将使您保持更新。@Vimal:您必须在调用wait/notify的同一对象上进行同步。但是为什么不能在两个线程中的同一个监视器上等待/通知呢?如果我在这些线程中使用同一个监视器,那么在
monitor.notify()上就可以了
它通知两个线程,并且读写也是异步的。@Vimal,但我认为您只想让读卡器等待,直到写操作完成?如果写卡器不等待,它将继续将数据写入输出文件。因此,需要的是,它应该只在新日志可用时写入文件。写入程序将数据写入文件后,读取器必须立即读取数据并将其发送到服务器。因此,OP。您通常对多线程代码有多满意?中的主题看起来熟悉吗?考虑到J2ME的局限性,我认为这是我见过的最好的相关介绍seen@gnat,谢谢你的链接,读起来真的很有见地。是的,我对多线程移动环境和开发非常满意。请检查我的问题描述,我已经编辑了同步实现。我现在正在研究的下一个问题是,如何从我已经上传到服务器的最后一个位置智能地从文件中读取足够的字节,这是一种传统的方法,即使用多个变量来记录添加/删除的字节数。我正在探索一个优化的实现方法。对于下一个问题,你考虑了阻塞队列吗?Jenkov的书中有一章有解释和代码。如果我理解正确,“THREAD-FILE-WRITE”将
enqueue
而“THREAD-FILE-READ”将
dequeue
@gnat,是的。正如您所说,它将排队和退队,我可以通过对监视器进行顺序化来实现这一点。现在我最关心的问题是如何有效地从文件中读取足够多的字节,这些字节由写入程序写入并发送到服务器。我知道我可以通过使用存储文件中字节的当前和新位置的变量来实现这一点,但我的目标是优化方法bcoz(a)它的IO操作是资源密集型的&(b)这将在通知读取队列的很多时间发生。我在想一些更简单的方法来解决上述问题。我明白了。看起来你正朝着有趣的方向前进就排队而言,您必须设计什么、何时以及如何排队?