如何在Java中以非常快的速度从文件中检索数据

时间:2017-06-26 14:27:07

标签: java multithreading file sockets

我有一种情况,我提供了一个由字符串组成的日志文件。我要做的是,我需要从文件中检索每个字符串并通过一个Socket,当文件的结尾到达时,它必须再次转到文件的开头并再次发送字符串。我使用发送字符串的无限线程编写了一个简单的代码,当EOF出现时,我关闭文件并再次使用新的BufferedReader对象重新打开文件。而且我也给了少量5ms的线程休眠,但过了一段时间我的进程进入Pause状态(就像一个死锁)。反正有提高转移的速度吗?或者我可以消除暂停状态。

以下是我的简单代码:

public class Write extends Thread{

private static final String FileName = "Messages.txt";
private static final int port = 8080;
private final int time = 5;
ServerSocket  serverSocket;
Socket writeSocket;

@Override
  public void run()
  {
    try
    {
            serverSocket = new ServerSocket(port);
            System.out.println("Server listening on port " + port+ " ...");
            Socket writeSocket = serverSocket.accept();
            System.out.println("Connected to Client : "+ writeSocket.getLocalSocketAddress());

            OutputStream outStream = writeSocket.getOutputStream();
            PrintWriter out = new PrintWriter(outStream, true);
            BufferedReader input = new BufferedReader(new FileReader(FileName));
            String str = "";
            while(true)
            {
                str = input.readLine();

              if(str==null ){
                 input.close();
                 input = new BufferedReader(new FileReader(FileName));
            }

               else{
                System.out.println("Outgoing Message>>"+str);
                out.println(str);
                Thread.sleep(time);
               }
            }

    }
    catch(IOException e) {System.out.println(e); } catch (InterruptedException ex) {
        Logger.getLogger(Write.class.getName()).log(Level.SEVERE, null, ex);
    }
  }

}

让我给你一个简单的解释。考虑上面的代码是在服务器代码中。当我在同一台PC上运行客户端机器时,我能够以某种(高)速度发送消息,但在一段时间后,客户端和服务器都进入暂停状态。我觉得这就像一个死锁。客户端显示服务器已断开连接并再次连接。当我关闭客户端时,服务器再次启动。谁能告诉我有没有办法以极高的速度处理字符串?

3 个答案:

答案 0 :(得分:0)

重新阻止程序,我建议:

  1. System.out.print("A")之前加out.println(),之后加System.out.print("B")。如果它以“A”作为输出中的最后一条消息阻塞,则问题出在客户端(它们不会消耗数据,最终导致发送方阻塞)。
  2. 如果出现上一种情况,请编写自己的简单客户端,只读取套接字中的数据并将其丢弃,这样就可以证明问题出在另一边。
  3. 重新加速,您要删除sleepSystem.out.println

答案 1 :(得分:0)

为什么不使用java nio来读取所有行? https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#readAllLines-java.nio.file.Path-java.nio.charset.Charset- 或者文件太大而无法做到这一点?

答案 2 :(得分:0)

您的代码读取日志文件就好了。不需要让它更快。看下面(我评论了处理套接字的代码部分,代码在多次读取日志文件时运行良好。没有减速或死锁的迹象):

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Write extends Thread {

    private static final String FileName = "/tmp/Messages.txt";
    private static final int port = 8080;
    private final int time = 5;
    ServerSocket serverSocket;
    Socket writeSocket;

    public static void main(String[] args) {
        Write write = new Write();

        Thread thread = new Thread(new Write());
        thread.start();

    }

    @Override
    public void run() {
        try {
//            serverSocket = new ServerSocket(port);
//            System.out.println("Server listening on port " + port + " ...");
//            Socket writeSocket = serverSocket.accept();
//            System.out.println("Connected to Client : " + writeSocket.getLocalSocketAddress());
//
//            OutputStream outStream = writeSocket.getOutputStream();
//            PrintWriter out = new PrintWriter(outStream, true);
            BufferedReader input = new BufferedReader(new FileReader(FileName));
            String str = "";
            while (true) {
                str = input.readLine();

                if (str == null) {
                    input.close();
                    input = new BufferedReader(new FileReader(FileName));
                } else {
                    System.out.println("Outgoing Message>>" + str);
                    //out.println(str);
                    Thread.sleep(time);
                }
            }

        } catch (IOException e) {
            System.out.println(e);
        } catch (InterruptedException ex) {
            Logger.getLogger(Write.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}