简单说下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()) 并发运行,例如下面的代码片段

 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
 ; i < 10; i++) {
     final int index = i;
     fixedThreadPool.execute(new Runnable() {

         @Override
         public void run() {
             try {
                 Log.d("******", Thread.currentThread().getId() + "  thread name: " + Thread.currentThread().getName()+"--"+index);
                 Thread.sleep(2000);
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
     });
 }

运行结果如下

因为线程池大小为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() 是怎样联系的 :

 package cn.mr.ams.threadpool;

 import android.app.Activity;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;

 import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;

 public class MyActivity extends Activity {

     CyclicBarrier barrier = );
      ;
     public final Object myTPLock = new Object();//对象锁,主要用来实现同步,我这里并没有使用
     public static ExecutorService myTP = null;//和 AsyncTask() 连用
     );//第一种构造函数
     //private List<String> test = new ArrayList<String>();

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

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_my);
         //采用 第二种 构造方法,改写下 线程工厂 对象,使每次加入线程池中的线程都能被设置定义的属性
         myTP = Executors.newFixedThreadPool(3, new ThreadFactory() {
             @Override
             public Thread newThread(Runnable r) {
                 Thread t = new Thread(r);
                 //我把所加入到改线程池的线程全改名了
                 t.setName("LinGuanHong");
                 // 设置线程的优先级别
                 t.setPriority(Thread.NORM_PRIORITY - 1);
                 return t;
             }
         });
         for(String item : test) {
             //通过 for 循环,把 AsyncTask() 异步线程逐个 加入到线程池中
             new myThread(barrier).executeOnExecutor(myTP,item);
             //SystemClock.sleep(10);//能起到一定的延时,实现按顺序进行
         }
         /*for (int i = 0; i < 10; i++) {
             final int index = i;
             myTP_1.execute(new Runnable() {
                 @Override
                 public void run() {
                     try {
                         Log.d("******", Thread.currentThread().getId() + "  thread name: " + Thread.currentThread().getName()+"--"+index);
                         Thread.sleep(2000);
                     } catch (InterruptedException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
             });
         }*/

     }

 public class myThread extends AsyncTask<Object, Void, String> {
     private CyclicBarrier barrier = null;
     public myThread(CyclicBarrier barrier){
         this.barrier = barrier;
     }

     @Override
     protected String doInBackground(Object[] params) {
         Object id = params[0];
         String idString = id.toString();
         //synchronized (myTPLock) {
         Log.d("******", idString + " id: " + Thread.currentThread().getId() + "  " +
                 "thread name: " + Thread.currentThread().getName()+" "+MyActivity.j);
         //}
         MyActivity.j++;
         return null;
     }
 }

     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // Inflate the menu; this adds items to the action bar if it is present.
         getMenuInflater().inflate(R.menu.my, menu);
         return true;
     }

     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         // Handle action bar item clicks here. The action bar will
         // automatically handle clicks on the Home/Up button, so long
         // as you specify a parent activity in AndroidManifest.xml.
         int id = item.getItemId();
         if (id == R.id.action_settings) {
             return true;
         }
         return super.onOptionsItemSelected(item);
     }
 }

运行结果

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

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

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

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

java线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用的更多相关文章

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

    转载请声明出处谢谢!http://www.cnblogs.com/linguanh/ 这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲 ...

  2. Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  3. Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  4. Java线程池ThreadPoolExecutor使用和分析(一)

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  5. Java线程池ThreadPoolExecutor类源码分析

    前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...

  6. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  7. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  8. Java 线程池(ThreadPoolExecutor)原理解析

    在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...

  9. Java线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

随机推荐

  1. bootstrap table 和 x-editable 使用方法

    最近需要做一些数据表格,有同事推荐EasyUI,但经过比较还是选择了Bootstrap,一款极为强大的表格组件,基于Bootstrap 的 jQuery .本文还将介绍Bootstrap-editab ...

  2. Git 中 SSH key 生成步骤

    由于本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以必须要让github仓库认证你SSH key,在此之前,必须要生成SSH key. 第1步:创建SSH Key.在windows下 ...

  3. Python中strip()、lstrip()、rstrip()用法详解

    Python中有三个去除头尾字符.空白符的函数,它们依次为: strip: 用来去除头尾字符.空白符(包括\n.\r.\t.' ',即:换行.回车.制表符.空格)lstrip:用来去除开头字符.空白符 ...

  4. Android Design Support Library使用详解——TextInputLayout与TextInputEditText

    TextInputLayout 在谷歌的Material Design中,文本输入是这样表现的:当用户点击输入框想要输入文字时,如果输入框是空的,那么它的提示文字(hint)就会变小并且同时移动到输入 ...

  5. 【Android应用开发】RecycleView API 翻译 (文档翻译)

    . RecyclerView extends ViewGroupimplements ScrollingView NestedScrollingChild java.lang.Object    ↳ ...

  6. Bootstrap3 代码-用户输入

    通过 <kbd> 标签标记用户通过键盘输入的内容. To switch directories, type cd followed by the name of the directory ...

  7. 准备在CSDN知识库建立一个Ext JS的知识库

    CSDN近期正在建立一个知识库,目标是打造身边的技术百科全书 ,我觉得这创意挺好,就像stackoverflow一样,常见的问题在里面基本都有了,只要通过搜索就能找到所需的答案. 现在,大家对于Ext ...

  8. Spark-SQL之DataFrame操作大全

    Spark SQL中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的DataFra ...

  9. Thread Pools

    许多程序会动态创建数十个设置上百个线程.举个例子,一个web服务器可能在每一个新到来的请求时创建一个新线程,然后在请求完成后将其终止. 然而,创建一个新线程将会带来一定的耗费:它需要在内核中创建自身必 ...

  10. Swift基础之UIPickerView和小animate的使用

    写一个简单的UIPickerView的使用Demo,比较简单,其中和一个小动画的结合使用 UIPickerView的使用基本上跟OC语言中的一样,就是写法的样式问题,想必开发过OC的应该不需要多讲了, ...