java 多个线程操作同一文件夹下的文件 代码,遇到的问题及解决方案
程序员文章站
2022-05-30 11:54:02
...
最近课程需要,写了一个抓取新浪微博数据存入文件中再将文件所在路径传给服务器的小程序,主要思想是,两个线程,一个用来从新浪微博不断抓取数据,实时地新建文件,写入文件,另一个线程则负责在这些文件所在的文件夹中实时地读取文件,得到文件名列表,将没传给服务器的文件名传给服务器。
代码如下(只贴一个演示原理的代码吧):
主程序
- public static void main(String[] args) throws Exception
- {
- //抓取微博数据并写入D:\\weibo\\status\\,D:\\weibo\\comment\\
- WBDataRetriver retriver = new WBDataRetriver();
- retriver.start();
- //读取D:\\weibo\\status\\ 目录中的文件,把文件夹中文件名列出来发送服务器
- Client statusReader = new Client("D:\\weibo\\status\\");
- statusReader.start();
- //读取D:\\weibo\\comment\\ 目录中的文件,把文件夹中文件名列出来发送服务器
- Client commentReader = new Client("D:\\weibo\\comment\\");
- commentReader.start();
- }
//client 线程,当文件夹中有新的文件加进来的时候能提取新加入的文件名传给服务器,传的字符串格式自定义
- import java.io.File;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.net.InetAddress;
- import java.net.Socket;
- import java.util.HashSet;
- public class Client extends Thread
- {
- private Socket client;
- private HashSet<String> isReaden;
- //这里先不从server读取确认信息
- // private BufferedReader in;
- private PrintWriter out;
- private String filePath;
- public Client(String filePath) throws Exception, IOException
- {
- this.isReaden = new HashSet<String>();
- this.client = new Socket(InetAddress.getLocalHost(), 9081);
- // this.in = new BufferedReader(new
- // InputStreamReader(this.client.getInputStream()));
- this.out = new PrintWriter(this.client.getOutputStream());
- this.filePath = filePath;
- }
- public HashSet<String> getIsReaden()
- {
- return isReaden;
- }
- public boolean isReaden(String fileName)
- {
- if (fileName == null || this.isReaden.contains(fileName))
- {
- return true;
- }
- this.isReaden.add(fileName);
- return false;
- }
- public void run()
- {
- try
- {
- process();
- }
- catch (Exception e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- public void process() throws Exception
- {
- File file = null;
- while (true)
- {
- file = null;
- file = new File(this.filePath);
- File[] fileArray = file.listFiles();
- // 遍历文件列表
- for (int i = 0; i < fileArray.length; i++)
- {
- // 如果是文件类型
- if (fileArray[i].isFile())
- {
- String fileName = fileArray[i].getName().trim();
- // 如果已读取的文件中没有这个文件,则发送
- if (!isReaden(fileName))
- {
- String[] temp = fileName.split("_");
- // if (temp.length < 3)
- // {
- // continue;
- // }
- String url = "1&"
- + fileArray[i].getAbsolutePath()
- + "&"
- + temp[0]
- + "&"
- + temp[1]
- + "&"
- + temp[2];
- // 发送给服务器内容!
- System.out.println("sent to server : " + url);
- out.println(url);
- out.flush();
- }
- else
- {
- continue;
- }
- }
- }
- // // 注意这里!!!输出从server中读取的内容,如果server返回的内容中不包含/n则readline会堵塞在这里 不进入下一个循环
- // String temp = in.readLine();
- // if (temp.contains("end"))
- // {
- // break;
- // }
- // else
- // {
- // System.out.println("server said : " + temp);
- // }
- // //每隔3秒重复读取
- sleep(300);
- }
- // client.close();
- }
- }
//server端 比较简单的输出接收的文件名并返回给client一个反馈
- import java.net.*;
- import java.io.*;
- public class Server extends Thread {
- private Socket server;
- public Server(Socket c) {
- this.server = c;
- }
- public void run() {
- try {
- BufferedReader in = new BufferedReader(new InputStreamReader(
- server.getInputStream()));
- PrintWriter out = new PrintWriter(server.getOutputStream());
- while (true) {
- String str = in.readLine();
- System.out.println(str);
- out.println("received "+str);
- out.flush();
- if (str.equals("end"))
- break;
- }
- server.close();
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- public static void main(String[] args) throws IOException {
- ServerSocket server = new ServerSocket(9081);
- while (true) {
- Server mu = new Server(server.accept());
- mu.start();
- }
- }
- }
运行程序时发现一个问题,写文件的线程正常运行,不断产生新文件,但是两个读文件的线程却像被‘卡住’了,不能增量读取新加入的文件名给服务器,开始时还在想难道是多线程共同操作一个文件夹也需要什么锁吗,后来发现不是!注意client中while的后半部分(被注释掉的几行),这里client等待server反馈并输出从server中读取的内容,但是如果server返回的内容中不包含/n则readline会堵塞在这里 不进入下一个循环,因此造成“卡住”的情况,所以两端之间的通信内容要注意格式(这里如果client一定要输出服务器的反馈,那么可以对服务器返回的内容做一些处理,比如如果客户端送过来的内容是null的,也返回一个带/n的串)。
顺带着了解了java的HashSet和ArrayList和Array的比较,见这位博主的链接:http://www.diybl.com/course/3_program/java/javajs/20071111/85300.html
谢谢zz指点~加油~