`
sunhuaer123
  • 浏览: 6350 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Java并行开发笔记6

    博客分类:
  • java
阅读更多
对于持有线程的服务,只要服务的存在时间大于创建线程的方法的存在时间,那么就应该提供生命周期方法。

    在下面的程序中给出了一个简单的日志服务示例,其中日志操作在单独的日志线程中执行。产生日志消息的线程并不会将消息直接写入输出流,而是由LogWriter通过BlockingQueue将消息提交给日志线程,并由日志线程写入。这是一种多生产者单消费者(Multiple-Producer,Single-Consumer)的设计方式:每个调用log的操作都相当于一个生产者,而后台的日志线程则相当于消费者。如果消费者的处理速度低于生产者的生成速度,那么BlockingQueue将阻塞生产者,直到日志线程有能力处理新的日志消息。

 

   不支持关闭的生产者-消费者日志服务

public class LogWriter {
	private static final int CAPACITY = 5;
	private final BlockingQueue<String> queue;
	private final LoggerThread logger;
	
	public LogWriter(Writer writer){
		this.queue = new LinkedBlockingDeque<String>(CAPACITY);
		this.logger = new LoggerThread(writer);
	}
	
	public void start(){
		logger.start();
	}
	
	public void log(String msg) throws InterruptedException{
		queue.put(msg);
	}
	
	private class LoggerThread extends Thread{
		private final PrintWriter writer;
		
		public LoggerThread(Writer writer){
			this.writer = (PrintWriter) writer;
		}
		
		public void run(){
			try{
				while(true){
					writer.println(queue.take());
				}
			}catch(InterruptedException innored){
			}finally{
				writer.close();
			}
		}
	}
}

    一般地,像Logwriter这样的服务在软件产品中能发挥实际的作用,还需要实现一种终止日志线程的方法,从而避免使JVM无法正常关闭。

   一种关闭LogWriter的方法是:设置某个“已请求关闭”标志,以避免进一步提交日志消息。但存在竞态问题,提供可靠关闭操作能够解决该问题,因而要使日志消息的提交操作成为原子操作。具体代码如下:

public class LogService {
	private static final int CAPACITY = 5;
	private final BlockingQueue<String> queue;
	private final LoggerThread loggerThread;
	private final PrintWriter writer;
	
	@GuardedBy("this") private boolean isShutdown;
	@GuardedBy("this") private int reservations;  //预约
	
	public LogService(PrintWriter writer){
		this.queue = new LinkedBlockingQueue<String>(CAPACITY);
		this.writer = writer;
		loggerThread = new LoggerThread();
	}
	
	
	public void start(){
		loggerThread.start();
	}
	
	public void stop(){
		synchronized(this){
			isShutdown = true;
		}
		loggerThread.interrupt();
	}
	
	public void log(String msg) throws InterruptedException{
		synchronized(this){
			if(isShutdown){
				throw new IllegalStateException("...");
			}
			++reservations;
		}
		queue.put(msg);
	}
	
	private class LoggerThread extends Thread{
		public void run(){
			try{
					while(true){
						try{
							synchronized(LogService.this){
								if(isShutdown && reservations == 0){
									break;
								}
							}
							String msg = queue.take();
							synchronized(LogService.this){
								--reservations;
							}
							writer.println(msg);
						}catch(InterruptedException e){
							/* retry */
						}
					}
			  }finally{
				writer.close();
			  }
		}
	}
}

   另外一种关闭生产者-消费者服务的方式就是使用“毒丸(Poison Pill)”对象:“毒丸”是指一个放在队列上的对象,其含义是:“当得到这个对象时,立即停止”。 示例代码如下:

public class IndexingService {
	private static final File POISON = new File("");
	private final IndexerThread consumer = new IndexerThread();
	private final CrawlerThread producer = new CrawlerThread();
	private final BlockingQueue<File> queue = new LinkedBlockingDeque<File>();
	private final File root = new File("root");
	
	
	
	public void start(){
		producer.start();
		consumer.start();
	}
	
	public void stop(){
		producer.interrupt();
	}
	
	public void awaitTermination() throws InterruptedException{
		consumer.join();
	}
	
	
	public class CrawlerThread extends Thread{
		public void run(){
			try{
				crawl(root);
			}catch(InterruptedException e){
				/* 发生异常 */
			}finally{
				while(true){
					try{
						queue.put(POISON);
						break;
					}catch(InterruptedException e1){
						/*  重新尝试 */
					}
				}
			}
		}
		private void crawl(File root) throws InterruptedException{
			/*....*/
		}
	}
	public class IndexerThread extends Thread{
		public void run(){
			try{
				while(true){
					File file = queue.take();
					if(file == POISON){
						break;
					}else{
						indexFile(file);
					}
				}
			}catch(InterruptedException consumed){
				
			}
		}

		private void indexFile(File file) {
			/* ... */
		}
	}	
}
分享到:
评论

相关推荐

    java精华学习笔记

    Java精华学习笔记主要涵盖了Java编程语言的核心概念、关键特性以及实战技巧。这些笔记是作者在深入学习Java过程中积累的经验总结,旨在帮助初学者快速...通过深入学习和实践,可以逐步精通Java编程,应对各种开发挑战。

    B站java狂神说笔记

    【Java狂神说笔记】是针对Java开发语言深入学习的一份综合笔记,涵盖了广泛的Java相关知识点,适合初学者和有一定经验的开发者进行提升。这份笔记的PDF版本详细讲解了Java的基础概念、进阶特性和实战应用,旨在帮助...

    java学习好用的笔记

    Java是一种广泛使用的面向对象的编程...通过系统学习和实践,初学者可以逐步掌握Java编程,为后续的软件开发和系统设计打下坚实的基础。在阅读笔记时,结合实际编写代码,不断练习和调试,是提升Java技能的最佳途径。

    Java JDK 7学习笔记 PDF

    Java JDK 7是Java开发工具包的一个重要版本,它的全称是Java Development Kit,是用于构建和运行Java应用程序的关键组件。这个PDF学习笔记是开发者深入理解JDK 7特性和功能的重要参考资料。以下是对Java JDK 7的一些...

    达内core_java学习笔记

    理解线程的并发执行、同步机制(如synchronized关键字和Lock接口)以及线程通信,对于开发高效并行程序非常重要。 九、反射与注解 反射机制允许在运行时动态地获取类的信息并操作类的对象。注解是一种元数据,用于...

    李兴华java1.8视频笔记

    反射机制在Java中的应用广泛,特别是在框架开发和各种底层API中。 类集框架是Java集合框架的简称,提供了表示和操作集合的接口和类。Java集合框架主要包括Collection接口和Map接口,以及它们的多个子接口和实现类。...

    java JDK 8学习笔记

    Java JDK 8是Java开发工具集的一个重要版本,它的发布带来了许多创新特性和改进,极大地提升了开发者的工作效率。本学习笔记旨在深入解析JDK 8的关键特性,帮助初学者快速掌握这一版本的核心知识。 1. **lambda...

    java8学习笔记

    标题“java8学习笔记”表明了这是一份关于Java 8版本的学习资料,Java 8是Java编程语言的一个重要版本,它在2014年发布,包含了许多新的特性,例如lambda表达式、新的日期时间API、Stream API、接口中的默认方法和...

    最全的java学习笔记(必看).pdf

    Java中的线程是程序执行流的最小单位,提供并行计算的能力。Thread类用于表示线程,可以通过创建Thread类的子类或实现Runnable接口来创建线程。 JDK的安装和配置对于Java开发至关重要。路径(PATH)和类路径...

    JAVA JDK6 学习笔记

    **Java JDK6 学习笔记概述** Java JDK6(Java Development Kit 6)是Oracle公司发布的一个用于开发Java应用程序的重要工具集,包含了JRE(Java Runtime Environment)和一系列的开发和调试工具。这个版本的JDK发布...

    Java与生活-Markdown格式的笔记

    涵盖了Java的各个方面,包括但不限于IO流(模拟生活中的数据传输)、线程(如同生活中的并行任务)、网络编程(如互联网上的通信)以及Java的库和框架(如Spring框架在软件开发中的角色,就像生活中的基础设施,简化...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

     《java jdk 7学习笔记》适合java的初中级读者,以及广大java应用开发人员。 作译者 林信良(网名:良葛格) 学历:台湾大学电机工程学系 经历:台湾升阳教育训练技术顾问、专业讲师,oracle授权训练中心讲师 ...

    Java堆栈内存分析笔记

    本笔记将深入探讨这两个区域的工作原理以及如何进行有效的分析。 首先,我们要理解Java内存的两个主要部分:堆(Heap)和栈(Stack)。堆主要用于存储对象实例,而栈则用于存储基本类型变量和对象引用。堆内存是...

    Java大数据课程核心笔记

    Java大数据课程核心笔记是针对那些想要深入理解和应用Java在大数据领域的开发者所准备的宝贵资源。这份笔记涵盖了Java的基础以及在大数据处理中的应用,适合不同层次的学习者,无论你是初入编程殿堂的新手,还是有着...

    随时更新-小白实习生的Java学习笔记.rar

    Java是世界上最流行的编程语言之一,尤其在企业级应用开发中占据主导地位。这份"随时更新-小白实习生的Java学习笔记.rar"压缩包包含了实习生在学习Java过程中积累的知识点,主要涵盖了Java的基础、数据库操作、多...

    Java JDK 8学习笔记 带完整书签(不是页码书签哦)

    在Java JDK 8中,引入了一系列重大更新,极大地提升了开发效率和代码的可读性。首先,书中会详细讲解Lambda表达式,这是Java 8的核心特性之一。Lambda允许将匿名函数作为方法参数传递,简化了多线程编程和事件处理,...

    java高并发笔记.docx

    【Java高并发笔记】 在Java开发中,处理高并发场景是一项关键技能,涉及到多个核心概念。以下是关于同步、异步、并发、并行、临界区、阻塞、非阻塞以及死锁、饥饿和活锁的详细解释。 1. **同步与异步** - **同步*...

    java学习笔记JDK6课件和课本代码

    本资源"java学习笔记JDK6课件和课本代码"聚焦于JDK 6版本,这是一个较早但仍然有其价值的Java版本,因为许多遗留系统仍基于它。 JDK 6发布于2006年,引入了多项改进和新特性,如增强的Swing组件、改进的JDBC API、...

    黑马程序员_java8新特性详解笔记和源码

    Java 8是Java语言发展的一个重要里程碑,引入了许多创新性的特性和改进,极大地提升了开发效率和代码质量。本文将深入探讨Java 8的三大关键新特性:接口的默认方法实现、Lambda表达式以及一系列相关的变化。 一、...

Global site tag (gtag.js) - Google Analytics