java多线程读取文件夹中的多个文件问题,新手多谢!

zychere 2014-04-30 11:41:39
现在想利用多线程读取一个文件夹中的多个xml文件,但是现在每个线程都把所有文件全部读一遍,我希望的是一个线程读过的文件,其他线程就不去读了,请问我的代码错在什么地方?本人新手,多谢!
ps:我也试过每读一个文件就把它从列表里删除,还是不行。。
package comparison;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

public class CompareTest {
public static void main(String args[]){
read read = new read();
new Thread(read, "线程1").start();
new Thread(read, "线程2").start();
new Thread(read, "线程3").start();
new Thread(read, "线程4").start();
new Thread(read, "线程5").start();
// List<String> list = read.readXML();
// for(String s:list){
// System.out.println(s);
// }
}
}

class read implements Runnable{
@Override
public void run() {
File f = new File("d:"+File.separator+"comparetest");
File[] filePaths = f.listFiles();
List<File> filePathsList = new ArrayList<>();
for(File s:filePaths){
filePathsList.add(s);
}
//解析xml
SAXBuilder builder = new SAXBuilder();
List<String> xmlList = new ArrayList<>();
for(int i=0;i<filePathsList.size();i++){
synchronized(this){
try {
Thread.sleep(300);
} catch (InterruptedException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
InputStream is = new FileInputStream(filePathsList.get(i));
System.out.println("当前使用的线程是:"+Thread.currentThread().getName()+",正在读文件:"+filePathsList.get(i)+",列表当前长度:"+filePathsList.size());
Document doc = builder.build(is);
Element root = doc.getRootElement();
List<Element> list = root.getChildren();
for(Element e:list){
xmlList.add(e.getChildTextTrim("ERROR_FEEDBACK_ID"));
}
xmlList.add("--------------------------");
} catch (JDOMException | IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}

// public synchronized List<String> readXML(){
//
//// }
// return xmlList;
// }
}
...全文
3997 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
你的十二大爷 2016-05-13
  • 打赏
  • 举报
回复
lantuling 2014-11-15
  • 打赏
  • 举报
回复
一个问题,就是为啥要使用 多线程,这个文件读写不是多线程 有意义么
冰思雨 2014-05-05
  • 打赏
  • 举报
回复
import java.io.File;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;


public class Test_15 {

	public static final int THREAD_POOL_SIZE = 5;
	private final File POISON = new File("");
	private final BlockingQueue<File> files = new LinkedBlockingQueue<File>(1000);
	private final ConcurrentLinkedQueue<String> infos = new ConcurrentLinkedQueue<String>();
	private Thread[] pool = null;
	private volatile boolean running = false;
	
	public Test_15() {
		this(THREAD_POOL_SIZE);
	}
	
	public Test_15(int poolSize) {
		pool = new Thread[poolSize];
		FileWorker worker = new FileWorker();
		for(int i=0;i<pool.length;i++){
			pool[i] = new Thread(worker,"线程"+(i+1));
			pool[i].start();
		}
		running = true;
	}
	
	private class FileWorker implements Runnable {
		@Override
		public void run() {
			File file = null;
			try {
				while((file=files.take()) != POISON){
					try {
						doWork(file);
					} catch (Exception e) {
						onException(e,file);
					}
				}
				files.put(POISON);
			} catch (InterruptedException e) {
			}
		}

		private void onException(Exception e, File file) {
			e.printStackTrace();
		}

		private void doWork(File file) {
			// 解析XML
            SAXBuilder builder = new SAXBuilder();
            try {
                System.out.println("当前使用的线程是:"
                        + Thread.currentThread().getName() + ",正在读文件:"
                        + file.getName() + ",列表当前长度:"
                        + files.size());
                Document doc = builder.build(file);
                Element root = doc.getRootElement();
                List<Element> list = root.getChildren();
                for (Element e : list) {
                	infos.add(e.getChildTextTrim("ERROR_FEEDBACK_ID"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
		}
	}
	
	public void addFile(File file) throws InterruptedException{
		files.put(file);
	}
	
	public void addFilesIgnoreInterrupted(File[] files) {
		for(File file : files){
			try {
				this.files.put(file);
			} catch (InterruptedException e) {
			}
		}
	}
	
	public void shutdown(){
		try {
			if(running){
				running = false;
				files.put(POISON);
			}
		} catch (InterruptedException e) {
		}
	}
	
	public void waiting(){
		if(running || !files.contains(POISON)){
			throw new IllegalStateException("You must call shutdown() function before.");
		}
		for(Thread t : pool){
			try {
				t.join();
			} catch (InterruptedException e) {
			}
		}
	}
	
	public Queue<String> getInfos(){
		return infos;
	}
	
	public static void main(String[] args) {
		Test_15 instance = new Test_15();
		File folder = new File("d:\\comparetest");
		instance.addFilesIgnoreInterrupted(folder.listFiles());
		instance.shutdown();
		instance.waiting();
		for(String info : instance.getInfos()){
			System.out.println(info);
		}
	}

}
yuhouqingchen_2648 2014-05-05
  • 打赏
  • 举报
回复
上面代码还有个小bug,如下是在你基础上进行最小改动的
public class CompareTest {
	public static void main(String args[]) {
		read read = new read();
		new Thread(read, "线程1").start();
		new Thread(read, "线程2").start();
		new Thread(read, "线程3").start();
		new Thread(read, "线程4").start();
		new Thread(read, "线程5").start();
	}
}

class read implements Runnable {
	List<File> filePathsList = new ArrayList<File>();
	int index = 0;

	public read() {
		File f = new File("d:" + File.separator + "tmp");
		getFileList(f);
	}

	private void getFileList(File f) {
		File[] filePaths = f.listFiles();
		for (File s : filePaths) {
			if (s.isDirectory()) {
				getFileList(s);
			} else {
				if (-1 != s.getName().lastIndexOf(".xml")) {
					filePathsList.add(s);
				}
			}
		}
	}

	@Override
	public void run() {
		File file = null;
		while (index < filePathsList.size()) {
			synchronized (this) {
				if (index >= filePathsList.size()) {
					continue;
				}
				file = filePathsList.get(index);
				index++;
			}
			// 解析xml
			SAXBuilder builder = new SAXBuilder();
			List<String> xmlList = new ArrayList<String>();

			try {
				Thread.sleep(300);
			} catch (InterruptedException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
			try {
				InputStream is = new FileInputStream(file.getPath());
				System.out.println("当前使用的线程是:"
						+ Thread.currentThread().getName() + ",正在读文件:"
						+ filePathsList.indexOf(file) + ",列表当前长度:"
						+ filePathsList.size());
				Document doc = builder.build(is);
				Element root = doc.getRootElement();
				List<Element> list = root.getChildren();
				for (Element e : list) {
					xmlList.add(e.getChildTextTrim("ERROR_FEEDBACK_ID"));
				}
				xmlList.add("--------------------------");
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
}
yuhouqingchen_2648 2014-05-04
  • 打赏
  • 举报
回复
这是在你代码基础上进行最小改动的结果,你看看
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

public class CompareTest {
	public static void main(String args[]) {
		read read = new read();
		new Thread(read, "线程1").start();
		new Thread(read, "线程2").start();
		new Thread(read, "线程3").start();
		new Thread(read, "线程4").start();
		new Thread(read, "线程5").start();
	}
}

class read implements Runnable {
	List<File> filePathsList = new ArrayList<File>();
	int index = 0;

	public read() {
		File f = new File("d:" + File.separator + "tmp");
		getFileList(f);
	}

	private void getFileList(File f) {

		File[] filePaths = f.listFiles();
		for (File s : filePaths) {
			if (s.isDirectory()) {
				getFileList(s);
			} else {
				if (s.isFile() && -1 != s.getName().lastIndexOf(".xml")) {
					filePathsList.add(s);
				}
			}
		}
	}

	@Override
	public void run() {
		File file = null;
		while (index < filePathsList.size()) {
			synchronized (this) {
				file = filePathsList.get(index);
				if (file == null) {
					continue;
				}
				index++;
			}

			// 解析xml
			SAXBuilder builder = new SAXBuilder();
			List<String> xmlList = new ArrayList<String>();

			try {
				Thread.sleep(300);
			} catch (InterruptedException e2) {
				e2.printStackTrace();
			}
			try {
				InputStream is = new FileInputStream(file.getPath());
				System.out.println("当前使用的线程是:"
						+ Thread.currentThread().getName() + ",正在读文件:"
						+ filePathsList.indexOf(file) + ",列表当前长度:"
						+ filePathsList.size());
				Document doc = builder.build(is);
				Element root = doc.getRootElement();
				List<Element> list = root.getChildren();
				for (Element e : list) {
					xmlList.add(e.getChildTextTrim("ERROR_FEEDBACK_ID"));
				}
				xmlList.add("--------------------------");
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
	}
}
lasting00001 2014-04-30
  • 打赏
  • 举报
回复
可以用共享缓存和锁的方法解决
bichir 2014-04-30
  • 打赏
  • 举报
回复
new Thread(read, "线程1").start(); new Thread(read, "线程2").start(); new Thread(read, "线程3").start(); new Thread(read, "线程4").start(); new Thread(read, "线程5").start(); 这几个线程执行顺序我们是无法控制的,线程并发也是无法避免的。要实现你的功能那就只有一个办法让这5个线程之间有一个共识,就是让他们都知道除他之外的线程是否已经对某个文件进行了读取操作,如果已读取就不再读了。这就要用到线程之间的通信来完在。这里最好的办法就是定义一个全局变量,当一个线程一开始读取文件就把这个文件名信息存入这个全局变量中,别的线程读取时来判断一下那文件是否己经存到了全局变量中,如果已存在就不在讯取这个文件了。大体思路是这样的。所以你这个代码就得改一下在main中建一个全局变量LIST,然后把这个LIST传进这5个线程中来达到效果,当然也可以把list设成static这个好做一些。需要注意的是在每个线程中需要给这个全局的list加上线程锁,当任意一个线程对list进行操作时,让其他线程都处理等待状态。
linhua11 2014-04-30
  • 打赏
  • 举报
回复
我也觉得还是先分组最直接, 然后线程处理传给自己的那组文件就行了。 如果不能使用全局变量或者事先分组的情况下, 你得找个另外的方式来同步线程之间的信息,比如数据库或者数据文件。
铁匠梁老师 2014-04-30
  • 打赏
  • 举报
回复
先把文件夹下的文件分组,然后用传递参数的方式传给每个线程,这样每个线程就只解析自己的xml文件
zychere 2014-04-30
  • 打赏
  • 举报
回复
引用 1 楼 bichir 的回复:
new Thread(read, "线程1").start(); new Thread(read, "线程2").start(); new Thread(read, "线程3").start(); new Thread(read, "线程4").start(); new Thread(read, "线程5").start(); 这几个线程执行顺序我们是无法控制的,线程并发也是无法避免的。要实现你的功能那就只有一个办法让这5个线程之间有一个共识,就是让他们都知道除他之外的线程是否已经对某个文件进行了读取操作,如果已读取就不再读了。这就要用到线程之间的通信来完在。这里最好的办法就是定义一个全局变量,当一个线程一开始读取文件就把这个文件名信息存入这个全局变量中,别的线程读取时来判断一下那文件是否己经存到了全局变量中,如果已存在就不在讯取这个文件了。大体思路是这样的。所以你这个代码就得改一下在main中建一个全局变量LIST,然后把这个LIST传进这5个线程中来达到效果,当然也可以把list设成static这个好做一些。需要注意的是在每个线程中需要给这个全局的list加上线程锁,当任意一个线程对list进行操作时,让其他线程都处理等待状态。
感谢你的提示,现在问题基本解决了,只要把文件名称的list写在全局里就行了,不能卸载run方法里,另外我在run方法里加了synchronized就可以实现线程锁了吧?

62,634

社区成员

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

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