java 线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用。
转载请声明出处谢谢!http://www.cnblogs.com/linguanh/
这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲解。
简单说下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()异步线程加入到线程池中运行,能够很高效地提高执行任务的速度,如果不加其他操作限制,每个线程的执行可能是不按照顺序的,但是,他们却没有出现抢占资源的状况??
我的“区块链”技术书籍:《区块链以太坊DApp开发实战》
、
支付宝收款码 https://www.cnblogs.com/linguanh/gallery/825997.html
微信:https://www.cnblogs.com/linguanh/gallery/image/321906.html
银行卡:6217007200076746554 , 林冠宏
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?