`
xinbusiqq
  • 浏览: 4849 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
最近访客 更多访客>>
社区版块
存档分类
最新评论

java 多线程学习-----初入线程池

阅读更多
   使用线程池初衷
   最近项目做代码优化,有一业务功能,大致描述为有20几台分机往总机发送文件,总机在收到文件之后,会往分机反馈数据处理情况。
    这时候想到使用调度来查询总机收到的消息,处理之后分别发送至各分机,为避免排队处理,决定使用多线程,并使用线程池来管理。
    创建线程池
    查找资料之后,采用JDK1.5的java.util.concurrent包创建线程池,本例使用可重用固定线程数的线程池,代码如下:
	private static int maxThreads = 20;	//最大线程数
	private static ExecutorService e = Executors.newFixedThreadPool(maxThreads);	//创建一个有固定数量线程的线程池

    获取任务执行结果
    然后,我使用了FutureTask类来获取任务执行结果,并可以设置任务超时时间,代码如下:
FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true);
e.execute(ft);
Boolean fTaskResult = ft.get();  //不设置等待时间,等待计算完成,获取结果
//Boolean fTaskResult = ft.get(fTimeout, TimeUnit.SECONDS);  //设置等待时间,时间到了之后,获取任务执行结果,如果超时,则会抛出TimeoutException异常

    如果任务执行超时,我们可以调用FutureTask类的cancel(boolean mayInterruptIfRunning)方法来请求中断任务;
    参数mayInterruptIfRunning - 如果应该中断执行此任务的线程,则为 true;否则允许正在运行的任务运行完成,代码如下:
catch (TimeoutException e) {
		System.out.println("主线程等待计算结果超时,因此中断任务线程");
		ft.cancel(true);
}

   但是,这样存在一个问题,就是在调用FutureTask对象的get()方法时,会阻塞线程,直到任务执行完成,会阻止其他线程的执行,网上搜索无果,就用线程池又打开一个线程执行FutureTask对象的get()方法,代码如下:
	/**
	 * 执行任务
	 * @param t	线程对象
	 */
	public static void beginTask(Thread t){
		e.execute(t);
	}
	
	/**
	 * 不设置超时时间的任务调用
	 * @param key	线程标识
	 * @param t		线程对象
	 */
	public static void beginTask(String key,Thread thread){
		final String fKey = key;
		final FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true);
		runningTaskMap.put(key, ft);	//存储任务标识
		e.execute(ft);
		
		beginTask(new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub		
				try {			
					Boolean fTaskResult = ft.get();
					if(fTaskResult){
						System.out.println("key为:"+fKey+"的线程执行完成");						
					}
				} catch (InterruptedException e) {
					System.out.println("主线程在等待计算结果时被中断");
				} catch (ExecutionException e) {
					System.out.println("主线程等待计算结果,但计算抛出异常");
				}finally{
					runningTaskMap.remove(fKey);	//移除线程标识
				}
			}
		});
	}

   任务标记
   另外,为了能够获取正在执行的任务,我们对每个任务做了标记,存放在map集合中,代码如下:
	//创建一个带有标识的任务集合
	private static Map<String, FutureTask<Boolean>> runningTaskMap = Collections.synchronizedMap(new HashMap<String, FutureTask<Boolean>>());

   当每次调用线程池,就会往map集合中存放记录,调用完之后,再移除掉。
   我们也可以通过标识来中断正在执行的任务,代码如下:
	/**
	 * 根据传入的任务标识,来中断对应任务
	 * @param key	任务标识
	 */
	public static void intteruptTask(String key){
		FutureTask<Boolean> ft = runningTaskMap.get(key);
		ft.cancel(true);
		if(ft.isDone()){
			runningTaskMap.remove(key);
		}
	}

   最后附上完整代码:
package task.concurrent.threadPoor;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FixedThreadPool {
	private static int maxThreads = 20;	//最大线程数
	private static ExecutorService e = Executors.newFixedThreadPool(maxThreads);	//创建一个有固定数量线程的线程池
	
	//创建一个带有标识的任务集合
	private static Map<String, FutureTask<Boolean>> runningTaskMap = Collections.synchronizedMap(new HashMap<String, FutureTask<Boolean>>());
	
	/**
	 * 执行任务
	 * @param t	线程对象
	 */
	public static void beginTask(Thread t){
		e.execute(t);
	}
	
	/**
	 * 不设置超时时间的任务调用
	 * @param key	线程标识
	 * @param t		线程对象
	 */
	public static void beginTask(String key,Thread thread){
		final String fKey = key;
		final FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true);
		runningTaskMap.put(key, ft);	//存储任务标识
		e.execute(ft);
		
		beginTask(new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub		
				try {			
					Boolean fTaskResult = ft.get();
					if(fTaskResult){
						System.out.println("key为:"+fKey+"的线程执行完成");						
					}
				} catch (InterruptedException e) {
					System.out.println("主线程在等待计算结果时被中断");
				} catch (ExecutionException e) {
					System.out.println("主线程等待计算结果,但计算抛出异常");
				}finally{
					runningTaskMap.remove(fKey);	//移除线程标识
				}
			}
		});
	}
	
	/**
	 * 设置有超时时间的任务调用
	 * @param key		线程标识
	 * @param thread	线程对象
	 * @param timeout	秒
	 */
	public static void beginTask(String key, Thread thread, int timeout) {
		final String fKey = key;
		final int fTimeout = timeout;
		final FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true);
		runningTaskMap.put(key, ft);	//存储任务标识
		e.execute(ft);
		
		beginTask(new Thread(){
			@Override
			public void run() {
				// TODO Auto-generated method stub		
				try {			
					Boolean fTaskResult = ft.get(fTimeout, TimeUnit.SECONDS);
					if(fTaskResult){
						System.out.println("key为:"+fKey+"的线程执行完成");						
					}
				} catch (InterruptedException e) {
					System.out.println("主线程在等待计算结果时被中断");
				} catch (ExecutionException e) {
					System.out.println("主线程等待计算结果,但计算抛出异常");
				} catch (TimeoutException e) {
					System.out.println("主线程等待计算结果超时,因此中断任务线程");
					ft.cancel(true);
				}finally{
					runningTaskMap.remove(fKey);	//移除线程标识
				}
			}
		});
	}
	
	/**
	 * 根据传入的任务标识,来中断对应任务
	 * @param key	任务标识
	 */
	public static void intteruptTask(String key){
		FutureTask<Boolean> ft = runningTaskMap.get(key);
		ft.cancel(true);
		if(ft.isDone()){
			runningTaskMap.remove(key);
		}
	}
	
	/**
	 * 关闭线程池
	 */
	public static void shutDownPool(){
		e.shutdown();
	}
}


   总结:调用及测试代码就不贴出来了,由于是初写线程池代码,有很多不足之处,望网友能够指出,相互学习进步。
   参考资料:http://blog.csdn.net/hemingwang0902/article/details/4557304
http://westyi.iteye.com/blog/714935
不积跬步无以至千里
分享到:
评论

相关推荐

    java多线程学习-ftp上传

    Java多线程学习是编程领域中的重要一环,特别是在服务器端和网络编程中,多线程技术能够有效地利用系统资源,提高程序的并发性。FTP(File Transfer Protocol)上传则是通过网络将本地文件传输到远程服务器的过程。...

    JAVA线程、线程池资料----下载不扣分,回帖加1分,欢迎下载,童叟无欺

    在多线程大师Doug Lea的贡献下,在JDK1.5中加入了许多对并发特性的支持,例如:线程池。.......................................JAVA线程、线程池资料----下载不扣分,回帖加1分,欢迎下载,童叟无欺JAVA线程、...

    Java 多线程课程的代码及少量注释.zip

    Java 多线程主题1- Java 多线程启动线程2- Java 多线程Volatile – 基本线程通信3- Java 多线程同步4- Java 多线程锁对象5- Java 多线程线程池6- Java 多线程倒计时闩锁7- Java 多线程生产者-消费者8- Java 多线程...

    Java多线程学习-动力节点共22页.pdf.zip

    本资料“Java多线程学习-动力节点共22页.pdf.zip”提供了对Java多线程的深入学习,旨在帮助开发者掌握这一关键技术。 1. **线程基础**:Java中的线程是通过`Thread`类或者实现`Runnable`接口来创建的。通过继承`...

    WHUT-java多线程实验-第三周-文件上传和下载.zip

    在“WHUT-java多线程实验-第三周-文件上传和下载.zip”这个实验中,我们将重点探讨如何在多线程环境中实现文件的上传和下载功能。这个实验基于IntelliJ IDEA开发环境,它是一个流行的Java集成开发环境,提供了丰富的...

    Java多线程基础-01、数组概述.rar

    总的来说,"Java多线程基础-01、数组概述"的学习将帮助你理解如何在Java中创建和管理线程,以及如何在多线程环境下安全地使用数组。通过深入学习这部分内容,你将具备编写高效并发程序的基础,为后续的多线程编程...

    JAVA线程高级-线程按序交替执行

    在Java编程中,多线程是并发编程的重要组成部分,它允许程序同时执行多个任务,从而提高了系统的效率和响应性。然而,在某些场景下,我们可能需要控制线程的执行顺序,确保它们按照特定的顺序交替运行,这在并发编程...

    Java多线程-Socket编程

    Java 多线程-Socket 编程 Java 多线程-Socket 编程是指在 Java 语言中使用多线程技术来实现网络编程,特别是使用 Socket 编程来实现客户端和服务器端的通信。在 Java 中,多线程可以使用 Thread 类和 Runnable 接口...

    Java多线程--等待所有子线程执行完的五种方法.docx

    在Java多线程编程中,有时我们需要确保所有子线程执行完毕后再进行后续操作,例如在并发测试、数据聚合或资源清理等场景。本篇文章将详细介绍五种在Java中等待所有子线程执行完的方法。 ### 方法一:使用`sleep`...

    线程-线程池-锁-集合-Map-队列.docx

    线程的状态管理是多线程编程中非常重要的部分。Java线程有六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED。NEW表示线程刚创建还未启动,RUNNABLE表示线程在执行或等待CPU资源,BLOCKED表示...

    Java多线程编程总结

    Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 Java线程:新特征-锁(上) Java线程:新特征-锁(下) Java线程:新特征-信号量 Java线程:新特征-阻塞队列 Java线程:新特征-阻塞栈 Java线程:新特征-...

    WHUT-java多线程实验-第二周-异常处理.zip

    在"WHUT-java多线程实验-第二周-异常处理"这个实验中,我们将学习如何在多线程环境下进行异常捕获和处理。实验基于IntelliJ IDEA这个强大的Java集成开发环境进行,IDEA提供了友好的界面和丰富的工具,方便我们进行...

    JAVA并发编程实践-线程池-学习笔记

    Java并发编程实践中的线程池是一个关键的概念,它在多线程编程中扮演着至关重要的角色,有效地管理和调度线程资源,以提高系统的性能和效率。线程池通过复用已存在的线程来减少线程的创建和销毁开销,避免了频繁的上...

    Java多线程编程,生命游戏,用线程池.zip

    Java多线程编程,生命游戏,用线程池.zipJava多线程编程,生命游戏,用线程池.zip Java多线程编程,生命游戏,用线程池.zipJava多线程编程,生命游戏,用线程池.zip Java多线程编程,生命游戏,用线程池.zipJava多...

    java多线程查询数据库

    综上所述,"java多线程查询数据库"是一个涉及多线程技术、线程池管理、并发控制、分页查询等多个方面的复杂问题。通过理解和掌握这些知识点,我们可以有效地提高数据库操作的效率和系统的响应速度。

    Java多线程Executors批量执行数据实现限流

    Java多线程实现数据切割批量执行,实现限流操作。 java线程池Executors实现数据批量操作。 批量异步Executors处理数据,实现限流操作,QPS限流。 线程池调用第三方接口限流实现逻辑。 案例适合: 1.批量处理大数据。...

    java多线程分页查询

    ### Java多线程分页查询知识点详解 #### 一、背景与需求分析 在实际的软件开发过程中,尤其是在处理大量数据时,如何高效地进行数据查询成为了一个关键问题。例如,在一个用户众多的社交平台上,当用户需要查看...

    java多线程例子-生产者消费者

    在本示例中,“java多线程例子-生产者消费者”旨在展示如何利用多线程来实现生产者和消费者模式。这种模式是并发编程中的经典设计模式,用于协调生产数据和消费数据的两个不同线程。 生产者消费者模式的基本概念是...

    JAVA使用线程池查询大批量数据

    除了`ThreadPoolExecutor`,Java还提供了`Executors`工具类,它提供了一些预设的线程池配置,如`newFixedThreadPool`(固定大小线程池)、`newSingleThreadExecutor`(单线程线程池)等,方便开发者快速创建线程池。...

Global site tag (gtag.js) - Google Analytics