CoreJava_线程并发(堵塞队列):在某个目录下搜索含有某keyword的文件

Java多线程编程是很考验一个程序猿水平的。

传统的WEB程序中。由于框架提供了太多的健壮性、并发性、可靠性的支持,所以我们都是将全部的注意力放到了业务实现上。我们不过依照业务逻辑的要求。不停的积累自己的代码。

由于知识,或者是经验的限制。常常出现了问题而不自知。

比如,某些比較原始的项目中。并没有使用Spring等相对来说比較灵活健壮的框架。

而是只使用Servlet来作为服务端的实现方式。

举一个简单的栗子。众所周知,当请求到了容器,容器是创建而且启动了一个Servlet线程来对当前的请求作出对应,这个时候。Servlet中的成员变量就会受到多线程的影响。这样,在Servlet中书写成员变量代码就会变得很的危急。由于毕竟不是一个线程安全的设计。多线程的同步、相互排斥、竞争、配合以及线程的中断等成了我们在编码过程中。很注意的一个知识点。

Java核心技术中。说到怎样对多线程进行并发控制:首先:建议使用堵塞队列。堵塞队列是由专业的线程安全的一个数据结构。我们在这个上面进行编程,就如同站在巨人的肩膀上,至于非常多低层的实现就是他们去考虑的事情了。其次,假设想自己控制多线程并发的时候,尽可能的推荐使用synchronizedkeyword,synchronizedkeyword实际上就是等同于ReentrantLock或者读写锁的实现,只是语法更加简洁。更不太easy出错。FINALLY。最后,假设有充足的理由的时候,才会推荐使用ReentrantLock或者ReentrantReadWriteLock、ReadLock、WriteLock以及其对应的condition条、volatile等等,由于这些太过于低层,并且依照java一贯的实现编码逻辑,我们仅仅须要知道某一个控制线程并发数据结构的存在就能够了。

以下是在核心技术上的一个非常好的。能够用来研究堵塞队列的Demo。目的是用于在某一个给定的目录以下。搜索全部含有某个keyword的文件,这中功能在非常多编辑器下都有详细的实现。比如UE。

功能的实现方式大概是这种:生产者线程,将当前给定的目录以下的全部的文件,放到堵塞队列中(功能实现中使用了递归),最后,放置一个空的文件,作为一个标志。类似于一个信号灯的样子。创建了非常多的消费者线程,从堵塞队列中,循环获取一个文件,然后进行逐行遍历,假设其中含有keyword则打印。跳出循环的条件是看到了消费者线程放置的信号灯。功能的实现将并发依赖于一个并发的数据结构。非常值得去借鉴。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueTest {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.println("Enter base directory(eg. /usr/local/jdk1.6.0/src)");
		String directory = in.nextLine();
		System.out.println("Enter keyword(e.g. volatile):");
		String keyword = in.nextLine();

		final int FILE_QUEUE_SIZE=10;
		final int SEARCH_THREADS =100;

		BlockingQueue<File> queue = new ArrayBlockingQueue<File>(FILE_QUEUE_SIZE);

		FileEnumerationTask enumerator = new FileEnumerationTask(queue,new File(directory));
		new Thread(enumerator).start();
		for(int i=1;i<=SEARCH_THREADS;i++){
			new Thread(new SearchTask(queue,keyword)).start();
		}
	}
}

class FileEnumerationTask implements Runnable{

	public FileEnumerationTask(BlockingQueue<File> queue,File startingDirectory){
		this.queue=queue;
		this.startingDirectory = startingDirectory;
	}
	@Override
	public void run() {
		try{
			enumerate(startingDirectory);
			queue.put(DUMMY);
		}catch(InterruptedException e){
		}
	}
	public void enumerate(File directory)throws InterruptedException{
		File[] files = directory.listFiles();
		for(File file : files){
			if(file.isDirectory())enumerate(file);
			else queue.put(file);
		}
	}
	public static File DUMMY = new File("");

	private BlockingQueue<File> queue;
	private File startingDirectory;
}

class SearchTask implements Runnable{
	public SearchTask(BlockingQueue<File> queue,String keyword){
		this.queue = queue;
		this.keyword = keyword;
	}
	@Override
	public void run() {
		try {
			boolean done = false;
			while(!done){
				File file = queue.take();
				if(file==FileEnumerationTask.DUMMY){
					queue.put(file);
					done=true;
				}
				else {
					search(file);
				}
			}
		}catch(IOException e){

		}
		catch (InterruptedException e) {
		}
	}

	private void search(File file)throws IOException{
		Scanner in = new Scanner(new FileInputStream(file));
		int lineNumber = 0;
		while(in.hasNextLine()){
			lineNumber++;
			String line = in.nextLine();
			if(line.contains(keyword))System.out.printf("%s:%d:%s%n",file.getPath(),lineNumber,line);
		}
		in.close();
	}

	private BlockingQueue<File> queue;
	private String keyword;
}
时间: 2025-02-01 12:11:11

CoreJava_线程并发(堵塞队列):在某个目录下搜索含有某keyword的文件的相关文章

CoreJava_线程并发(阻塞队列):在某个文件夹下搜索含有某关键字的文件

Java多线程编程是非常考验一个程序员水平的.传统的WEB程序中,因为框架提供了太多的健壮性.并发性.可靠性的支持,所以我们都是将所有的注意力放到了业务实现上.我们只是按照业务逻辑的要求,不停的积累自己的代码.因为知识,或者是经验的限制,经常出现了问题而不自知.例如,某些比较原始的项目中,并没有使用Spring等相对来说比较灵活健壮的框架.而是仅仅使用Servlet来作为服务端的实现方式. 举一个简单的栗子,众所周知,当请求到了容器,容器是创建并且启动了一个Servlet线程来对当前的请求作出相

FileFilter 遍历某个目录下文件名含有某个字符的文件

由于IIS版本的升级,造成了文件名中含有“+”的特殊字符的文件(多数是图片)在网页中不能被访问,于是必须查找当前目录下含有多少这样的文件,从而制定最佳的解决方案. 废话少说,直接上核心代码: public void GetAllFilesInDirectory(string strDirectory, string searchCh) { DirectoryInfo directory = new DirectoryInfo(strDirectory); DirectoryInfo[] dire

Java版本的删除指定目录下名叫“xxx.txt”文件名的文件

以前写过一个python版本的,但是在查找文件路径的时候出现错误,无法正确的获取到文件的路径,就造成无法删除该路径下的“xxx.txt”文件. 当时以为是windows版本系统的错误造成这个问题的,也就没有继续深究,就把这个bug给放过了. 最近一段时间在学习android,肯定要用的java了,就用java实现了下,思路的话,肯定还是以前的了,结果还是出错,后来仔细的看了看代码,其实是自己的bug. 把代码贴下:(主要功能,删除指定目录下名叫"pylist.txt"的所有文件,使用递

计算目录下的md5值,用于文件被篡改后对比

计算/etc目录下的md5值,用于文件被篡改后对比,命令如下: find /etc/ -maxdepth 1 -type f | xargs -n1 md5sum> /root/etc_sum-$(date +%F).log 同样的道理, 我们可以将/usr/bin  /usr/sbin/ /usr/local/bin /root/bin 等等重要的目录下面的文件校验和都计算一遍,这样的话定期执行一下该命令,生成一份最新的校验和,通过diff命令将生成的log文件和原始的md5sum.log比较

查找目录下匹配.py或者.txt的文件

#!/usr/bin/python def endWith(s,*endstring_1):       #*代表允许传输多个参数,名称统一为endstring为元祖,**为字典 array = map(s.endswith,endstring_1)  #map(调用的函数名称,给这个函数传的参数) if True in array: return True else: return False if __name__ == '__main__': import os s = os.listdi

Java使用递归找出某目录下的所有子目录以及子文件

1 /* 2 使用递归找出某目录("C:\\JavaProducts")下的所有子目录以及子文件 3 */ 4 5 import java.util.*; 6 import java.io.*; 7 8 public class FileRecursionPrintDemo{ 9 public static void main(String[] args){ 10 List<String> paths = new ArrayList<String>(); 11

java移动文件夹、 慎用java file.renameTo(f)方法 、 java从一个目录复制文件到另一个目录下 、 java代码完成删除文件、文件夹 、

java移动文件夹(包含子文件和子文件夹): http://blog.csdn.net/yongh701/article/details/45070353 慎用java    file.renameTo(f)方法: http://www.cnblogs.com/mrwangblog/p/3934506.html 注意看结果,从C盘到E盘失败了,从C盘到D盘成功了.因为我的电脑C.D两个盘是NTFS格式的,而E盘是FAT32格式的.所以从C到E就是上面文章所说的"file systems"

/var/log目录下的20个Linux日志文件功能详解

如果愿意在Linux环境方面花费些时间,首先就应该知道日志文件的所在位置以及它们包含的内容.在系统运行正常的情况下学习了解这些不同的日志文件有助于你在遇到紧急情况时从容找出问题并加以解决. 以下介绍的是20个位于/var/log/ 目录之下的日志文件.其中一些只有特定版本采用,如dpkg.log只能在基于Debian的系统中看到. /var/log/messages - 包括整体系统信息,其中也包含系统启动期间的日志.此外,mail,cron,daemon,kern和auth等内容也记录在var

.Net 遍历目录下的子文件夹和文件

今天再完成一道任务的时候需要遍历得到所有txt文件,搜索很久终于得到了一个很方便的方法. foreach (string o in Directory.GetDirectories(@"D:\Logs") { foreach (string i in Directory.GetFiles(o)) { FileInfo fi = new FileInfo(i); if (fi.Extension.Equals(".txt")) { //这里我就可以操作我得到的满足条件