有一个data.xml文件,提供给网络用户读取使用.每一个用户每5秒钟就要读取一次.
在服务端,有一个程序每过几秒就将一些数据写入这个文件.(完全重新写入,不是追加)我现在遇到一个问题,当用户访问频率太高,写入动作就会有问题.有时写入后文件大小为0.现在程序已经上线运行,看不出问题在哪.测试环境下很难达到那样的访问频率,也不好测试.各位谁遇到过这样的情况给个解决思路也欢迎大家来讨论一下

解决方案 »

  1.   

    异常没有看到
    写入为大小为0,就是读取的时候发现那个文件是空的,size是0,打开后没有字符。这就是问题。
      

  2.   

    不要把你的xml文件直接暴露给用户,写一个jsp,让它返回xml,这中间进行线程保护,就不会出问题了。还可以通过公共属性或者类的静态变量来在内存中操作xml,比如声明一个类,它的某个静态变量xmlStr为String类型,存放xml,对所有的读写操作都在synchronized(xmlStr){}块内部进行。
      

  3.   

    你们说的我明白
    如果取文件是我自己处理,那当然好办了。还用什么jsp呀,一个servlet就okay了,那也不用写data.xml,直接在内存中处理就可以了
    可是java的http容器性能存在问题,用户用的是tomcat,大访问量早趴下了。只能交给iis来处理
    所以我才生成xml文件的。这样我就没办法做同步了。
      

  4.   

    把xml文件写入到别的位置,然后复制到用户可以下载的位置。
      

  5.   

    我把我的测试代码贴出来,大家不用看我代码,拷贝过去调试一下就知道了
    这个是读取数据文件的类
    启动时输入100之类的数字,表示读取线程数
    再输入读取文件的url,如file:\\\e:\a.txtpackage 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) {
                }
            }
        }
    }
      

  6.   


    下面是写文件类
    启动时输入写入类型,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秒。本以为很简单的东西,怎么还碰了壁了呢
      

  7.   

    测试代码都贴出来了,难道没人看一眼吗
    至少新手也可以从这里学习一下文件操作和url操作呀帮忙顶一下啊
      

  8.   

    饿死就是有些程序或线程长时间无法申请到需要的资源“如果采用拷贝的方法,读取时会出现很长时间读取的都是同一个文件”
    就是用File.nameTo方法将新生成的文件改名为目标文件,(可能由于目标文件在被使用,结果改名失败)目标文件很可能没有被替换,结果客户读取的数据都是原来的旧数据。
      

  9.   

    跑了一次  看了一下,谈谈我的看法 和楼主交流
    如果选择直接写入,读取时会出现size=0的情况,如果read线程很多,这种现象越明显
    如果采用拷贝的方法,读取时会出现很长时间读取的都是同一个文件关于这个问题,MS你采用的是时间片轮转的方法,可能是在时间片用完的时候,数据还没有从缓冲池中写入文件 ,造成文件为空。试试时间片稍微大一点? 采用拷贝的话,是不是缓冲池中间没有清空?  (乱说的,不要在意)对于io操作的互斥和饿死现象我就不多说了
    互斥 应该实现了,饿死我认为不会出现呀,轮转本身就是一种抢占式调度算法,会出现饿死状况?只是这样的需求怎么实现呢?
      

  10.   

    写入方式,读取长度为0,我和你的看法基本相同
    拷贝我感觉不是缓冲的问题.很可能是原文件正在被read,这是新文件要拷贝到原文件上可能出现失败.这样就可能出现拷贝不成功,而读取的都是相同内容真正的饿死是不会出现,但读取太频繁,造成文件实际上一直处于被读取状态,那写入线程实际上很难得到文件的操作权.现象上类似于饿死现在的问题是怎么实现我这样的需求呢?
      

  11.   

    有没有考虑这样:设置2个文件:A,B。当B写入完成后就由B来提供用户读取,要重新写入时,服务器端往A文件写入完成之后就由A文件供用户读取,这样循环 是不是好一些?LZ参考看看