zoukankan      html  css  js  c++  java
  • 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;
    }
    



  • 相关阅读:
    方向
    CSS笔记2 css中的伪类
    CSS 笔记1 css选择器
    0employee_attr抽取性能慢
    用程序读取Query,模拟APD将数据存到直接更新的DSO
    生产环境无法修改,如何调整分析权限
    BW通过函数调用Query,设置传入参数,动态设置输出维度
    EXCEL使用公式去除一列中的重复项
    修改已释放传输请求
    BW使用函数模块自定义数据源
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5346880.html
Copyright © 2011-2022 走看看