文件写入的方案征集 大家一起来讨论

fool_leave 2007-06-19 10:41:43
有一个data.xml文件,提供给网络用户读取使用.每一个用户每5秒钟就要读取一次.
在服务端,有一个程序每过几秒就将一些数据写入这个文件.(完全重新写入,不是追加)

我现在遇到一个问题,当用户访问频率太高,写入动作就会有问题.有时写入后文件大小为0.

现在程序已经上线运行,看不出问题在哪.测试环境下很难达到那样的访问频率,也不好测试.

各位谁遇到过这样的情况给个解决思路

也欢迎大家来讨论一下



...全文
317 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
mengpiao_shuiya 2007-06-26
  • 打赏
  • 举报
回复
试过了!
谢搂主!
tdy1234 2007-06-25
  • 打赏
  • 举报
回复
跑了一次 看了一下,谈谈我的看法 和楼主交流
如果选择直接写入,读取时会出现size=0的情况,如果read线程很多,这种现象越明显
如果采用拷贝的方法,读取时会出现很长时间读取的都是同一个文件

关于这个问题,MS你采用的是时间片轮转的方法,可能是在时间片用完的时候,数据还没有从缓冲池中写入文件 ,造成文件为空。试试时间片稍微大一点?

采用拷贝的话,是不是缓冲池中间没有清空? (乱说的,不要在意)

对于io操作的互斥和饿死现象我就不多说了
互斥 应该实现了,饿死我认为不会出现呀,轮转本身就是一种抢占式调度算法,会出现饿死状况?

只是这样的需求怎么实现呢?
fool_leave 2007-06-25
  • 打赏
  • 举报
回复
up
tdy1234 2007-06-25
  • 打赏
  • 举报
回复
有没有考虑这样:设置2个文件:A,B。当B写入完成后就由B来提供用户读取,要重新写入时,服务器端往A文件写入完成之后就由A文件供用户读取,这样循环 是不是好一些?LZ参考看看
fool_leave 2007-06-25
  • 打赏
  • 举报
回复
写入方式,读取长度为0,我和你的看法基本相同
拷贝我感觉不是缓冲的问题.很可能是原文件正在被read,这是新文件要拷贝到原文件上可能出现失败.这样就可能出现拷贝不成功,而读取的都是相同内容

真正的饿死是不会出现,但读取太频繁,造成文件实际上一直处于被读取状态,那写入线程实际上很难得到文件的操作权.现象上类似于饿死

现在的问题是怎么实现我这样的需求呢?
fool_leave 2007-06-22
  • 打赏
  • 举报
回复
这个问题很实际的
各位都想想,测测吧
yingzi107 2007-06-22
  • 打赏
  • 举报
回复
程序员群 41801837
fool_leave 2007-06-21
  • 打赏
  • 举报
回复
up
高手可在乎?
fool_leave 2007-06-20
  • 打赏
  • 举报
回复
测试代码都贴出来了,难道没人看一眼吗
至少新手也可以从这里学习一下文件操作和url操作呀

帮忙顶一下啊
fool_leave 2007-06-20
  • 打赏
  • 举报
回复
饿死就是有些程序或线程长时间无法申请到需要的资源

“如果采用拷贝的方法,读取时会出现很长时间读取的都是同一个文件”
就是用File.nameTo方法将新生成的文件改名为目标文件,(可能由于目标文件在被使用,结果改名失败)目标文件很可能没有被替换,结果客户读取的数据都是原来的旧数据。
weihthchk 2007-06-20
  • 打赏
  • 举报
回复
这个情况真有意思,还真是一时想不到好办法。
请教一下,什么是“饿死”?
“如果采用拷贝的方法,读取时会出现很长时间读取的都是同一个文件”是怎么回事?
lixiaoxue85 2007-06-19
  • 打赏
  • 举报
回复
线程同步的问题
weihthchk 2007-06-19
  • 打赏
  • 举报
回复
不要把你的xml文件直接暴露给用户,写一个jsp,让它返回xml,这中间进行线程保护,就不会出问题了。还可以通过公共属性或者类的静态变量来在内存中操作xml,比如声明一个类,它的某个静态变量xmlStr为String类型,存放xml,对所有的读写操作都在synchronized(xmlStr){}块内部进行。
fool_leave 2007-06-19
  • 打赏
  • 举报
回复
异常没有看到
写入为大小为0,就是读取的时候发现那个文件是空的,size是0,打开后没有字符。这就是问题。

约翰羊 2007-06-19
  • 打赏
  • 举报
回复
up
zqrqq 2007-06-19
  • 打赏
  • 举报
回复
你说到:“当用户访问频率太高,写入动作就会有问题.有时写入后文件大小为0”

会出问题----具体是什么问题?有异常抛出吗?
有时写入后文件大小为0----是指什么?是不应该出现写入大小为0, 但是日志显示写入为0?or “写入大小为0”也是允许的 ?

等待具体的描述。。。


fool_leave 2007-06-19
  • 打赏
  • 举报
回复



下面是写文件类
启动时输入写入类型,1是直接写入,2是写入零时文件后拷贝过来

package write;

import java.io.*;

public class FileWriteThread implements Runnable {
static boolean isDestroy = false;
static int type;
private long times = 0;
public FileWriteThread() {
}

public void run() {
while (!isDestroy) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
switch (type) {
case 1:
writeFile1();
break;
case 2:
writeFile2();
break;
default:
System.out.println("Err write type");
}
System.out.println("Write times = " + times);
}
}

private void writeFile1() {
File f = new File("a.txt");
BufferedWriter bw = null;
FileWriter fw = null;
try {
fw = new FileWriter(f);
bw = new BufferedWriter(fw);
bw.write(""+times);
bw.newLine();
bw.flush();
for (int i = 0; i < 1000; i++) {
bw.write("index="+times);
bw.newLine();
bw.flush();
}
} catch (Exception ex) {
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException ex1) {
}
}
}
times++;
}

private void writeFile2() {
File f = null;
try {
f = File.createTempFile("tempwritefile", "temp");
} catch (Exception ex2) {
ex2.printStackTrace();
return;
}
BufferedWriter bw = null;
FileWriter fw = null;
try {
fw = new FileWriter(f);
bw = new BufferedWriter(fw);
bw.write(""+times);
bw.newLine();
bw.flush();
for (int i = 0; i < 1000; i++) {
bw.write("index="+times);
bw.newLine();
bw.flush();
}
} catch (Exception ex) {
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException ex1) {
}
}
}
File df=new File("a.txt");
df.delete();
f.renameTo(df);
f.delete();
times++;
}


public static void main(String args[]) {
int type = 0;
while (true) {
System.out.println("Input write type :");
byte buf[] = new byte[100];
int size = 0;
try {
size = System.in.read(buf);
if (size <= 0) {
continue;
}
String str = new String(buf, 0, size);
type = Integer.parseInt(str.trim());
if(type>3|| type<1){
System.out.println("Type should be 1,2,3");
continue;
}
FileWriteThread.type=type;
} catch (Exception ex1) {
}
break ;
}
new Thread(new FileWriteThread()).start();
while (true) {
try {
byte buf[] = new byte[100];
int size = System.in.read(buf);
if (size <= 0) {
continue;
}
String str = new String(buf, 0, size);
if (str.equalsIgnoreCase("exit")) {
FileWriteThread.isDestroy = true;
return;
}
} catch (Exception ex) {
}
}
}
}



运行后看看,会发现
如果选择直接写入,读取时会出现size=0的情况,如果read线程很多,这种现象越明显
如果采用拷贝的方法,读取时会出现很长时间读取的都是同一个文件

对于io操作的互斥和饿死现象我就不多说了
只是这样的需求怎么实现呢?

我这个data.xml是要给网页提供数据的,数据间隔大约就是3秒。本以为很简单的东西,怎么还碰了壁了呢
fool_leave 2007-06-19
  • 打赏
  • 举报
回复
我把我的测试代码贴出来,大家不用看我代码,拷贝过去调试一下就知道了


这个是读取数据文件的类
启动时输入100之类的数字,表示读取线程数
再输入读取文件的url,如file:\\\e:\a.txt

package read;

import java.io.*;
import java.net.*;

public class FileReaderThread implements Runnable {
static {
lock = new Object();
}
static boolean isDestroy = false;
static long readTime = 0;
static Object lock ;
static String filePath;
static long storedTimes=0;
public FileReaderThread() {
}

public void run() {
while (!isDestroy) {
readFile();
synchronized (lock) {
if (readTime %1000 == 0) {
System.out.println("Read times = " + readTime+",store times = "+storedTimes);
}
}
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}

private void readFile() {
long time=-1;
InputStreamReader isr = null;
long size = 0;
try {
URL url = new URL(filePath);
isr = new InputStreamReader(url.openConnection().getInputStream());
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
if(time<0){
time=Long.parseLong(line.trim());
}
size += line.trim().length();
}
} catch (Exception ex) {
ex.printStackTrace();
return;
} finally {
if (isr != null) {
try {
isr.close();
} catch (Exception ex1) {
}
}
}
if (size <=10) {
System.err.println("Size = "+size);
}
synchronized (lock) {
readTime++;
if(time>storedTimes){
storedTimes=time;
System.out.println("Stored times changed : "+storedTimes);
}
}
}

public static void main(String args[]) {
int num = 0;
while (true) {
System.out.println("Input read thread num:");
byte buf[] = new byte[100];
int size = 0;
try {
size = System.in.read(buf);
if (size <= 0) {
continue;
}
String str = new String(buf, 0, size);
num = Integer.parseInt(str.trim());
} catch (Exception ex1) {
}
break ;
}
while (true) {
System.out.println("Input file url:");
byte buf[] = new byte[1024];
int size = 0;
try {
size = System.in.read(buf);
if (size <= 0) {
continue;
}
String str = new String(buf, 0, size).trim();
try {
URL url = new URL(str);
} catch (MalformedURLException ex2) {
System.err.println("Err url !");
continue;
}
FileReaderThread.filePath=str;
} catch (Exception ex1) {
}
break ;
}
for (int i = 0; i < num; i++) {
new Thread(new FileReaderThread()).start();
} while (true) {
try {
byte buf[] = new byte[100];
int size = System.in.read(buf);
if (size <= 0) {
continue;
}
String str = new String(buf, 0, size);
if (str.equalsIgnoreCase("exit")) {
FileReaderThread.isDestroy = true;
return;
}
} catch (IOException ex) {
}
}
}
}
liujun999999 2007-06-19
  • 打赏
  • 举报
回复
先写到别的地方,然后再复制过来覆盖原来的文件
weihthchk 2007-06-19
  • 打赏
  • 举报
回复
把xml文件写入到别的位置,然后复制到用户可以下载的位置。
加载更多回复(1)

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧