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;
    }
    



  • 相关阅读:
    Spring Boot (20) 拦截器
    Spring Boot (19) servlet、filter、listener
    Spring Boot (18) @Async异步
    Spring Boot (17) 发送邮件
    Spring Boot (16) logback和access日志
    Spring Boot (15) pom.xml设置
    Spring Boot (14) 数据源配置原理
    Spring Boot (13) druid监控
    Spring boot (12) tomcat jdbc连接池
    Spring Boot (11) mybatis 关联映射
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5346880.html
Copyright © 2011-2022 走看看