java线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用

简介: 简单说下Executors类,提供的一系列创建线程池的方法: 他们都有两个构造方法 1. --------newFixedThreadPool (创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。) public static ExecutorService newFixedThreadPool (int nThreads); public static Ex

简单说下Executors类,提供的一系列创建线程池的方法:

他们都有两个构造方法

1. --------newFixedThreadPool

(创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。)

public static ExecutorService newFixedThreadPool (int nThreads);
public static ExecutorService newFixedThreadPool (int nThreads, ThreadFactory threadFactory);

2. --------newSingleThreadExecutor

(创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。)

public static ExecutorService newSingleThreadExecutor();
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);

3. --------newCachedThreadPool

(创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程)
public static ExecutorService newCachedThreadPool();
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);

4. --------newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。)

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);

*******************************************

定长线程池-newFixedThreadPool 的第一个构造方法

public static ExecutorService newFixedThreadPool(int nThreads);传入的参数nThreads是最大的同时进行、并发的线程数。如果我定义它是3,那么同时执行3个,超过的了就要排队等待,流水线操作形式。

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

这个构造函数的第一个参数和上面的一个样,第二个是线程工厂,它的作用:

文档中是这样说的 :

这是什么意思呢? 其实就是说,在把线程加入线程池之前,都对它们共同进行一些操作,例如改变一些属性。比如说setName(),thread-1和2、3、4 依次通过一个for 循环加入到线程池 中,他们的 Name 都会被改变。

线程池一般的使用方法:

通过 Executors.newFixedThreadPool(...).execute(Runnable()) 并发运行,例如下面的代码片段

 1 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
 2 for (int i = 0; i < 10; i++) {
 3     final int index = i;
 4     fixedThreadPool.execute(new Runnable() {
 5  
 6         @Override
 7         public void run() {
 8             try {
 9                 Log.d("******", Thread.currentThread().getId() + "  thread name: " + Thread.currentThread().getName()+"--"+index);
10                 Thread.sleep(2000);
11             } catch (InterruptedException e) {
12                 // TODO Auto-generated catch block
13                 e.printStackTrace();
14             }
15         }
16     });
17 }

运行结果如下

因为线程池大小为3,最多3个同时运行,每个输出index后sleep 2秒,所以每两秒打印3个数字。

线程池和AsyncTask()结合使用:

AsyncTask() 知识恶补入口:http://www.2cto.com/kf/201203/122729.html

这里只说下 AsyncTask()的executeOnExecutor() 方法, 它 是3.0后新增的一个方法。executeOnExecutor( Executor exec, Object ... params),

该方法接受2个参数:

第一个参数是 Executor ,即是我们的线程池实例,默认的可以传入AsyncTask.THREAD_POOL_EXECUTOR,多线程并发,我们上面的是自定义的线程池,默认的最大并发5个,队列最大128个,当然,我们可以new 一个ThreadPoolExecutor 实例,通过传入参数改变这些限制;

第二个是任务参数。即是AsyncTask()中的第一个参数,我们可以在doInBackground()中获取它,我下面的例子中,这个参数是字符串。

下面通过运行代码看看它和 AsyncTask() 是怎样联系的 :

  1 package cn.mr.ams.threadpool;
  2 
  3 import android.app.Activity;
  4 import android.os.AsyncTask;
  5 import android.os.Bundle;
  6 import android.util.Log;
  7 import android.view.Menu;
  8 import android.view.MenuItem;
  9 
 10 import java.util.concurrent.CyclicBarrier;
 11 import java.util.concurrent.ExecutorService;
 12 import java.util.concurrent.Executors;
 13 import java.util.concurrent.ThreadFactory;
 14 
 15 
 16 public class MyActivity extends Activity {
 17 
 18     CyclicBarrier barrier = new CyclicBarrier(3);
 19     public static int j = 0 ;
 20     public final Object myTPLock = new Object();//对象锁,主要用来实现同步,我这里并没有使用
 21     public static ExecutorService myTP = null;//和 AsyncTask() 连用
 22     public static ExecutorService myTP_1 = Executors.newFixedThreadPool(3);//第一种构造函数
 23     //private List<String> test = new ArrayList<String>();
 24 
 25     private String[] test = new String[]{"a--","b--","c--","d--","e--"};
 26 
 27     @Override
 28     protected void onCreate(Bundle savedInstanceState) {
 29         super.onCreate(savedInstanceState);
 30         setContentView(R.layout.activity_my);
 31         //采用 第二种 构造方法,改写下 线程工厂 对象,使每次加入线程池中的线程都能被设置定义的属性
 32         myTP = Executors.newFixedThreadPool(3, new ThreadFactory() {
 33             @Override
 34             public Thread newThread(Runnable r) {
 35                 Thread t = new Thread(r);
 36                 //我把所加入到改线程池的线程全改名了
 37                 t.setName("LinGuanHong");
 38                 // 设置线程的优先级别
 39                 t.setPriority(Thread.NORM_PRIORITY - 1);
 40                 return t;
 41             }
 42         });
 43         for(String item : test) {
 44             //通过 for 循环,把 AsyncTask() 异步线程逐个 加入到线程池中
 45             new myThread(barrier).executeOnExecutor(myTP,item);
 46             //SystemClock.sleep(10);//能起到一定的延时,实现按顺序进行
 47         }
 48         /*for (int i = 0; i < 10; i++) {
 49             final int index = i;
 50             myTP_1.execute(new Runnable() {
 51                 @Override
 52                 public void run() {
 53                     try {
 54                         Log.d("******", Thread.currentThread().getId() + "  thread name: " + Thread.currentThread().getName()+"--"+index);
 55                         Thread.sleep(2000);
 56                     } catch (InterruptedException e) {
 57                         // TODO Auto-generated catch block
 58                         e.printStackTrace();
 59                     }
 60                 }
 61             });
 62         }*/
 63 
 64     }
 65 
 66 
 67 public class myThread extends AsyncTask<Object, Void, String> {
 68     private CyclicBarrier barrier = null;
 69     public myThread(CyclicBarrier barrier){
 70         this.barrier = barrier;
 71     }
 72 
 73     @Override
 74     protected String doInBackground(Object[] params) {
 75         Object id = params[0];
 76         String idString = id.toString();
 77         //synchronized (myTPLock) {
 78         Log.d("******", idString + " id: " + Thread.currentThread().getId() + "  " +
 79                 "thread name: " + Thread.currentThread().getName()+" "+MyActivity.j);
 80         //}
 81         MyActivity.j++;
 82         return null;
 83     }
 84 }
 85 
 86 
 87     @Override
 88     public boolean onCreateOptionsMenu(Menu menu) {
 89         // Inflate the menu; this adds items to the action bar if it is present.
 90         getMenuInflater().inflate(R.menu.my, menu);
 91         return true;
 92     }
 93 
 94     @Override
 95     public boolean onOptionsItemSelected(MenuItem item) {
 96         // Handle action bar item clicks here. The action bar will
 97         // automatically handle clicks on the Home/Up button, so long
 98         // as you specify a parent activity in AndroidManifest.xml.
 99         int id = item.getItemId();
100         if (id == R.id.action_settings) {
101             return true;
102         }
103         return super.onOptionsItemSelected(item);
104     }
105 }

运行结果

在这里我们可以验证,我们采用第二种构造方法,在线程工厂中改变 各线程的名字。

在我的代码45行中,我通过for 循环有顺序地传入 a~e 字符串,但是这里的线程并没有按照顺序运行。即是并发了,因为AsyncTask本身是异步线程,我们再看上述代码19行,我设置了个静态的 int 标记,在 AsyncTask() 里面 78~81行没打一次 log 就++,按照我们对异步、并发线程的理解,和可能就会出现,输出的0~5是不按照顺序的,但是上面是按照顺序的,不仅仅是一次的截图,我自己测试过很多次,0~5的输出都是按顺序的。

我自己的总结,可能不一定对,有错请大家指出:

把AsyncTask()异步线程加入到线程池中运行,能够很高效地提高执行任务的速度,如果不加其他操作限制,每个线程的执行可能是不按照顺序的,但是,他们却没有出现抢占资源的状况??

目录
打赏
0
0
0
0
498
分享
相关文章
|
8天前
|
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
117 60
【Java并发】【线程池】带你从0-1入门线程池
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
127 2
|
4天前
|
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
40 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
|
2月前
|
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
121 17
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
174 1
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
280 64
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
143 38
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####
Java中的线程池深度解析####
本文深入探讨了Java并发编程中的核心组件——线程池,从其基本概念、工作原理、核心参数解析到应用场景与最佳实践,全方位剖析了线程池在提升应用性能、资源管理和任务调度方面的重要作用。通过实例演示和性能对比,揭示合理配置线程池对于构建高效Java应用的关键意义。 ####
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等