java async task_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);

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

文档中是这样说的:

894e6d59526c65089d6e91778e54af4a.png

这是什么意思呢? 其实就是说,在把线程加入线程池之前,都对它们共同进行一些操作,例如改变一些属性。比如说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(newRunnable() {5

6 @Override7 public voidrun() {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 }

运行结果如下

39844e722991936373adc3fa062fb5ba.png

因为线程池大小为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 packagecn.mr.ams.threadpool;2

3 importandroid.app.Activity;4 importandroid.os.AsyncTask;5 importandroid.os.Bundle;6 importandroid.util.Log;7 importandroid.view.Menu;8 importandroid.view.MenuItem;9

10 importjava.util.concurrent.CyclicBarrier;11 importjava.util.concurrent.ExecutorService;12 importjava.util.concurrent.Executors;13 importjava.util.concurrent.ThreadFactory;14

15

16 public class MyActivity extendsActivity {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 test = new ArrayList();

24

25 private String[] test = new String[]{"a--","b--","c--","d--","e--"};26

27 @Override28 protected voidonCreate(Bundle savedInstanceState) {29 super.onCreate(savedInstanceState);30 setContentView(R.layout.activity_my);31 //采用 第二种 构造方法,改写下 线程工厂 对象,使每次加入线程池中的线程都能被设置定义的属性

32 myTP = Executors.newFixedThreadPool(3, newThreadFactory() {33 @Override34 publicThread newThread(Runnable r) {35 Thread t = newThread(r);36 //我把所加入到改线程池的线程全改名了

37 t.setName("LinGuanHong");38 //设置线程的优先级别

39 t.setPriority(Thread.NORM_PRIORITY - 1);40 returnt;41 }42 });43 for(String item : test) {44 //通过 for 循环,把 AsyncTask() 异步线程逐个 加入到线程池中

45 newmyThread(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 @Override52 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 block58 e.printStackTrace();59 }60 }61 });62 }*/

63

64 }65

66

67 public class myThread extends AsyncTask{68 private CyclicBarrier barrier = null;69 publicmyThread(CyclicBarrier barrier){70 this.barrier =barrier;71 }72

73 @Override74 protectedString 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 @Override88 public booleanonCreateOptionsMenu(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 @Override95 public booleanonOptionsItemSelected(MenuItem item) {96 //Handle action bar item clicks here. The action bar will97 //automatically handle clicks on the Home/Up button, so long98 //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 }

运行结果

fc32c651ff890568175ccb4046053fdb.png

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值