`
jean7155
  • 浏览: 61529 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

自定义ThreadPoolExecutor

阅读更多
仍旧沿用ExecutorService的例子, 修改了AsyncImageLoader调用线程管理池的方法。

AsyncImageLoader的思路:
1. 自定义RejectedExecutionHandler, 当线程任务被拒绝时,使其等待线程管理池空余后继续被调用。
2. 自定义线程管理池ThreadPoolExecutor替代ExecutorService
3. 线程的主要任务DownloadThreadTask,加载图片
4. 所有任务完成后,关闭自定义的ThreadPoolExecutor

源码:
自定义的RejectedExecutionHandler
public class RejectedExcutionHandlerImpl implements RejectedExecutionHandler {

	@Override
	public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
		Log.i("test", ((DownloadThreadTask)r).getTask() + " is rejected");
		
                // 如果出现线程任务被拒绝,则等待一段时间后,再次创建并提交到线程池中
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		executor.execute(r);
		Log.i("test",((DownloadThreadTask)r).getTask() + "再次创建并提交");

	}
}



自定义的ThreadPoolExecutor
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
	
	public CustomThreadPoolExecutor(
			int corePoolSize, 
			int maximumPoolSize, 
			long keepAliveTime, 
			TimeUnit unit, 
			BlockingQueue<Runnable> workQueue,
			RejectedExecutionHandler handler){
		super(corePoolSize,maximumPoolSize, keepAliveTime, unit, workQueue, handler);
		
		
	}
        
        // beforeExecute, afterExecute方法一般用于日志中,记录任务被调用前和完成后的状态
	@Override
	protected void beforeExecute(Thread t, Runnable r) {
		super.beforeExecute(t, r);
		Log.i("test","perform before execute logic" + ((DownloadThreadTask)r).getTask());
	}

	@Override
	protected void afterExecute(Runnable r, Throwable t) {
		super.afterExecute(r, t);
		
		if (t != null) {
			Log.i("test","Perform exception handler logic" + ((DownloadThreadTask)r).getTask());
		}
		
		Log.i("test","Perform afterExecute() logic" + ((DownloadThreadTask)r).getTask());
	}

}


线程任务DownloadThreadTask
public class DownloadThreadTask implements Runnable {
	
	public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String,SoftReference<Drawable>>();
	
	private String task; // 任务名称
	private String url;  // 加载URL
	private Handler handler;
	private ImageCallback callback;
	
	public DownloadThreadTask(String task, String url, Handler handler, ImageCallback callback){
		this.task = task;
		this.url = url;
		this.handler = handler;
		this.callback = callback;
	}

	public String getTask() {
		return task;
	}
	public void setTask(String task) {
		this.task = task;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}

	public Handler getHandler() {
		return handler;
	}
	public void setHandler(Handler handler) {
		this.handler = handler;
	}
	@Override
	public void run() {
		try {  
			try{
				Thread.sleep(10);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			
            final Drawable drawable = loadImageFromUrl(url);
            imageCache.put(url, new SoftReference<Drawable>(drawable));

            handler.post(new Runnable() {  
                public void run() {  
                    callback.imageLoader(drawable);
                }  
            });  
            
            Log.i("test", "加载图片任务完成" + this.task);
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  


	}
	
	protected Drawable loadImageFromUrl(String imageUrl){
		 try {  
           return Drawable.createFromStream(new URL(imageUrl).openStream(), "image.png");  
    } catch (Exception e) {  
            throw new RuntimeException(e);  
    }  
		
	}

}


AsyncImageLoader
public class AsyncImageLoader {
	
	public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String,SoftReference<Drawable>>();
	
	private BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(2);
	private RejectedExecutionHandler myReject = new RejectedExcutionHandlerImpl();
	
	CustomThreadPoolExecutor executor = new CustomThreadPoolExecutor(1,2,5,TimeUnit.MILLISECONDS, blockingQueue, myReject);

	private final Handler handler = new Handler();

	public Drawable loadDrawable(final String task, final String imageUrl, final ImageCallback callback){
		
		if(imageCache.containsKey(imageUrl)){
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
			
			if(softReference.get()!=null){
				return softReference.get();
			}
		}
		Log.i("test","创建任务并提交到线程池中:" + task);
		executor.execute(new DownloadThreadTask(task, imageUrl, handler, callback));	
		
		try {
			Thread.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		return null;
	}
	
	
	
	public void shutdownAndAwaitTermination() {
		   executor.shutdown(); // Disable new tasks from being submitted

		   try {
		     // Wait a while for existing tasks to terminate
		     if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
		    	 executor.shutdownNow(); // Cancel currently executing tasks
			       // Wait a while for tasks to respond to being cancelled
		    	 Log.i("test", "i am shutting down...");
			       if (!executor.awaitTermination(60, TimeUnit.SECONDS))
			           System.err.println("Pool did not terminate"); 
		     }
		       
		     
		   }catch (InterruptedException ie) {
		     // (Re-)Cancel if current thread also interrupted
			   Log.e("test","something interrupted happend, and i am shutting down....");
		     executor.shutdownNow();
		     // Preserve interrupt status
		     //Thread.currentThread().interrupt();
		  }
	 }
}



下载的Activity对AsyncImageLoader的调用
public class BatchDownloadActivity extends Activity {
	
	private static final String fileRealName = "我的图片1.gif";
	private String url;
	private int id;
	private List<String> urls = new ArrayList<String>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
	
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.batch_download);
		
		String fileName = fileRealName;
		String url = "";
		
		try {
			url = ToolsUtil.getIpAddress() + URLEncoder.encode(fileRealName,"UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		Log.i("test","url=" + url);
		
		loadImage("task@1", url, R.id.imageView1);
		loadImage("task@2", url, R.id.imageView2);
		loadImage("task@3", url, R.id.imageView3);
		loadImage("task@4", url,R.id.imageView4);
		loadImage("task$5", url,R.id.imageView5);
		
		loader.shutdownAndAwaitTermination();
	
	}
	
	private AsyncImageLoader loader = new AsyncImageLoader();
	

	private void loadImage(final String task, final String url, final int id) {
		
		Drawable cacheImage = loader.loadDrawable(task, url,new ImageCallback() {  
				@Override
					public void imageLoader(Drawable imageDrawable) {
						
					     ((ImageView) findViewById(id)).setImageDrawable(imageDrawable);
					     Log.i(task, "loading new pic:" +url);
					}  
        });  

		if (cacheImage != null) {  
			((ImageView) findViewById(id)).setImageDrawable(cacheImage);  
			Log.i("test", "loading existing pic");
		}  
	}
	

}



---------------------------------------------------------------

以下使用 Callable 替代Runnable来进行图片的加载。 思路如上述所,只是修改一些源码。
1. 加载图片的 Callable
public class DownloadCallableTask implements Callable<Drawable> {
	
	public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String,SoftReference<Drawable>>();
	
	private String task;
	private String url;
	
	public DownloadCallableTask(String task, String url){
		this.task = task;
		this.url = url;
	}
	public String getTask(){
		return this.task;
	}

	@Override
	public Drawable call() throws Exception {
		  
		try{
			Thread.sleep(10);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
			
		if(imageCache.containsKey(url)){
			SoftReference<Drawable> softReference = imageCache.get(url);
				
			if(softReference.get()!=null){
				return softReference.get();
			}
		}
			
        final Drawable drawable = loadImageFromUrl(url);
        imageCache.put(url, new SoftReference<Drawable>(drawable));
           
        Log.i("test", "加载图片任务完成" + this.task);
          
        return drawable;
        
	}
	
	protected Drawable loadImageFromUrl(String imageUrl){
		 try {  
			 return Drawable.createFromStream(new URL(imageUrl).openStream(), "image.png");  
		 } catch (Exception e) {  
			 throw new RuntimeException(e);  
		 }
	}
	

}


2. AsyncCallableLoader 替代 AsyncImageLoader
public class AsyncCallableLoader {
	
	private BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(2);

	ThreadPoolExecutor executor = new ThreadPoolExecutor(1,2,5,TimeUnit.MILLISECONDS, blockingQueue);
	
	private final Handler handler = new Handler();

	public Drawable loadDrawable(final String task, final String imageUrl) throws InterruptedException, ExecutionException{

		Log.i("test","创建任务并提交到线程池中:" + task);
		final Future<Drawable> future = executor.submit(new DownloadCallableTask(task,imageUrl));
		
	
		try {
			Thread.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		return future.get();
		
	}
	
	
	
	public void shutdownAndAwaitTermination() {
		   executor.shutdown(); // Disable new tasks from being submitted

		   try {
		     // Wait a while for existing tasks to terminate
		     if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
		    	 executor.shutdownNow(); // Cancel currently executing tasks
			       // Wait a while for tasks to respond to being cancelled
		    	 Log.i("test", "i am shutting down...");
			       if (!executor.awaitTermination(60, TimeUnit.SECONDS))
			           System.err.println("Pool did not terminate"); 
		     }
		       
		     
		   }catch (InterruptedException ie) {
		     // (Re-)Cancel if current thread also interrupted
			   Log.e("test","something interrupted happend, and i am shutting down....");
		     executor.shutdownNow();
		     // Preserve interrupt status
		     //Thread.currentThread().interrupt();
		  }
	 }


}



3. Activity调用AsnycCallableLoader
private AsyncCallableLoader loader = new AsyncCallableLoader();
	

	private void loadImage(final String task, final String url, final int id) {
		
		Drawable cacheImage;
		try {
			cacheImage = loader.loadDrawable(task, url);
			if (cacheImage != null) {  
				((ImageView) findViewById(id)).setImageDrawable(cacheImage);  
				Log.i("test", "loading pic");
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
	}
分享到:
评论

相关推荐

    Java进阶之ThreadPoolExecutor

     · 使用自定义ThreadPoolExecutor  · 使用Executors.newCachedThreadPool()  · 使用Executors.newFixedThreadPool(int)  · 使用Executors.newSingleThreadExecutor()  其中使用2,3,4来创建线程池时...

    基于配置中心的轻量级动态线程池,内置监控告警功能,集成常用中间件线程池管理,可通过SPI自定义扩展实现

    轻量级动态线程池,内置监控告警功能,基于主流配置中心(已支持Nacos、Apollo、ZK,可通过SPI自定义实现)。对线程池 ThreadPoolExecutor 做一些扩展增强,主要实现以下目标:实现对运行中线程池参数的动态修改,...

    JAVA并发编程实践_中文版(1-16章全)_1/4

    真正的Addison-Wesley 出品的Java Concurrency in Practice 中文版 目录回到顶部↑ ...第14章 构建自定义的同步工具 第15章 原子变量与非阻塞同步机制 第16章 java存储模型 附录a 同步annotation 参考文献 索引

    Java并发编程part2

    中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea ...第14章 构建自定义的同步工具 第15章 原子变量与非阻塞同步机制 第16章 java存储模型

    Java并发编程实践part1

    中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea ...第14章 构建自定义的同步工具 第15章 原子变量与非阻塞同步机制 第16章 java存储模型

    完全解析Android多线程中线程池ThreadPool的原理和使用

    前言对于多线程,大家应该很熟悉。...开发者可根据不同需求 配置核心参数,从而实现自定义线程池 // 创建线程池对象如下 // 通过 构造方法 配置核心参数 Executor executor = new ThreadPoolExecutor

    Android开发艺术探索

     11.3.1 ThreadPoolExecutor / 407  11.3.2 线程池的分类 / 410  第12章 Bitmap的加载和Cache / 413  12.1 Bitmap的高效加载 / 414  12.2 Android中的缓存策略 / 417  12.2.1 LruCache / 418  12.2.2 ...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    11.3.1 ThreadPoolExecutor 407 11.3.2 线程池的分类 410 第12章 Bitmap的加载和Cache 413 12.1 Bitmap的高效加载 414 12.2 Android中的缓存策略 417 12.2.1 LruCache 418 12.2.2 DiskLruCache 419 12.2.3 ...

    zxing.java源码解析-StudyRoad:Java&Android开发知识点备忘

    zxing.java源码解析 ...ThreadPoolExecutor ​ 多进程 Socket ​ 网络编程 WebView 数据存储技术 ​ 多媒体 音频 视频 摄像头 位置与传感器 位置服务 其它传感器 硬件连接 蓝牙 NFC USB Wi-Fi P2P SIP 优秀开源框架

    Java并发编程实践 PDF 高清版

    随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序...第14章 构建自定义的同步工具 第15章 原子变量与非阻塞同步机制 第16章 Java存储模型 附录A 同步Annotation 参考文献 索引

    Android多线程:完全解析线程池ThreadPool原理&使用

    线程池中有6个核心参数,具体如下上述6个参数的配置决定了线程池的功能,具体设置时机=创建线程池类对象时传入ThreadPoolExecutor类=线程池的真正实现类开发者可根据不同需求配置核心参数,从而实现自定义线程池注:...

    J2SE技术总结-Java学习精华教程-电子书

    本书内容非常全面,涵盖了《Java编程思想》、《Java学习笔记》等书籍所有知识要点,并结合作者自己...线程池-ThreadPoolExecutor .....反射 ..........概述 ..........Class类 ..........类的加载 ..........操作对象

    Java并发编程(学习笔记).xmind

    配置ThreadPoolExecutor(自定义的线程池) 此处需要注意系统默认提供的线程池是如何配置的 扩展ThreadPoolExector GUI应用程序探讨 活跃度(Liveness)、性能、测试 避免活跃性危险 死锁 锁...

    Java并发编程实战

    如何识别可并行执行的任务,如何提高单线程子系统的响应性,如何确保并发程序执行预期任务,如何提高并发代码的性能和可伸缩性等内容,最后介绍了一些高级主题,如显式锁、原子变量、非阻塞算法以及如何开发自定义的...

    汪文君高并发编程实战视频资源全集

    ├─第一阶段 │ 源码+ppt.rar │ 高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第一阶段02讲、简单介绍什么是线程.wmv ... 高并发编程第三阶段40讲 ThreadPoolExecutor关闭(很重要)精讲...

    汪文君高并发编程实战视频资源下载.txt

    ├─第一阶段 │ 源码+ppt.rar │ 高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第一阶段02讲、简单介绍什么是线程.wmv ... 高并发编程第三阶段40讲 ThreadPoolExecutor关闭(很重要)精讲...

Global site tag (gtag.js) - Google Analytics