Android开发之线程&线程池姿势总结

Android 中的主线程和子线程

主线程(UI线程)主要用来处理四大组件间的交互,子线程用来做耗时操作(网络请求,I/O操作,sqlite操作等)

由于主线程比较特殊,因为本身主线程在处理界面上,用了大部分的消耗,所以主线程不能再处理过于耗时的操作(IO操作,网络请求,大量的数据操作),否则就会造成ANR现象(程序卡死)。

Activity响应时间超过5s
Broadcast在处理时间超过10s
Service处理时间超过20s

Android中的线程表现形式:

Thread、HanderThread、IntentService、AsyncTask、

HanderThread

HandlerThread 是一个包含 Looper 的 Thread,我们可以直接使用这个 Looper 创建 Handler。
HandlerThread 继承了Thread,它是一种可以使用 Handler 的 Thread,在 run 方法中通过 Looper.prepare() 来创建消息队列,并通过 Looper.loop() 来开启消息循环。

// 子线程中创建新的Handler 没有使用HandlerThread
new Thread () {
    @Override
    public void run() {
        Looper.prepare();
        Hnadler handler = new Handler();
        Looper.loop();
    } 
}

HandlerThread 的使用场景

我们知道,HandlerThread 所做的就是在新开的子线程中创建了 Looper,那它的使用场景就是 Thread + Looper 使用场景的结合,即:在子线程中执行耗时的、可能有多个任务的操作。
比如说多个网络请求操作,或者多文件 I/O 等等。

###使用流程

1.实例对象,参数为线程名字

HandlerThread handlerThread = new HandlerThread("handlerThread");

2.启动线程

handlerThread.start();

3.实例主线程的Handler,参数为HandlerThread内部的一个looper.

Handler handler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};

这里模拟的情况是我们在子线程下载东西,然后和主线程之间进行通信。主线程知道了下载开始和下载结束的时间,也就能及时改变界面UI。

首先是DownloadThread类,继承于HandlerThread,用于下载。

public class DownloadThread extends HandlerThread{

    private static final String TAG = "DownloadThread";

    public static final int TYPE_START = 2;//通知主线程任务开始
    public static final int TYPE_FINISHED = 3;//通知主线程任务结束

    private Handler mUIHandler;//主线程的Handler

    public DownloadThread(String name) {
        super(name);
    }

    /*
    * 执行初始化任务
    * */
    @Override
    protected void onLooperPrepared() {
        Log.e(TAG, "onLooperPrepared: 1.Download线程开始准备");
        super.onLooperPrepared();
    }

    //注入主线程Handler
    public void setUIHandler(Handler UIhandler) {
        mUIHandler = UIhandler;
        Log.e(TAG, "setUIHandler: 2.主线程的handler传入到Download线程");
    }

    //Download线程开始下载
    public void startDownload() {
        Log.e(TAG, "startDownload: 3.通知主线程,此时Download线程开始下载");
        mUIHandler.sendEmptyMessage(TYPE_START);

        //模拟下载
        Log.e(TAG, "startDownload: 5.Download线程下载中...");
        SystemClock.sleep(2000);

        Log.e(TAG, "startDownload: 6.通知主线程,此时Download线程下载完成");
        mUIHandler.sendEmptyMessage(TYPE_FINISHED);
    }
}

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private DownloadThread mHandlerThread;//子线程
    private Handler mUIhandler;//主线程的Handler

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //初始化,参数为线程的名字
        mHandlerThread = new DownloadThread("mHandlerThread");
        //调用start方法启动线程
        mHandlerThread.start();
        //初始化Handler,传递mHandlerThread内部的一个looper
        mUIhandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                //判断mHandlerThread里传来的msg,根据msg进行主页面的UI更改
                switch (msg.what) {
                    case DownloadThread.TYPE_START:
                        Log.e(TAG, "4.主线程知道Download线程开始下载了...这时候可以更改主界面UI");
                        break;
                    case DownloadThread.TYPE_FINISHED:
                        Log.e(TAG, "7.主线程知道Download线程下载完成了...这时候可以更改主界面UI,收工");
                        break;
                    default:
                        break;
                }
                super.handleMessage(msg);
            }
        };
        //子线程注入主线程的mUIhandler,可以在子线程执行任务的时候,随时发送消息回来主线程
        mHandlerThread.setUIHandler(mUIhandler);
        //子线程开始下载
        mHandlerThread.startDownload();
    }

    @Override
    protected void onDestroy() {
        //有2种退出方式
        mHandlerThread.quit();
        //mHandlerThread.quitSafely(); 需要API>=18
        super.onDestroy();
    }
}

运行log如下
在这里插入图片描述
总结如下:

  1. Handler是Android消息机制的上层接口,通过它可以轻松地将一个任务切换到Handler所在的线程中去执行,该线程既可以是主线程,也可以是子线程,要看构造Handler时使用的构造方法中传入的Looper位于哪里;
  2. Handler的运行需要底层的MessageQueue和Looper的支撑,Handler创建的时候会采用当前线程的Looper来构造消息循环系统,而线程默认是没有Looper的,如果需要使用Handler就必须为线程创建Looper;
    ActivityThread被创建时就会初始化Looper,这就是主线程中默认可以直接使用Handler的原因;
  3. Looper的工作原理:Looper在Android的消息机制中扮演着消息循环的角色,具体来说就是它会不停地从MessageQueue中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里。注意关注一些重要的Looper的方法:
    Looper.prepare()-为当前线程创建一个Looper;
    Looper.loop()-开启消息循环,只有调用该方法,消息循环系统才会开始循环;
    Looper.prepareMainLooper()-为主线程也就是ActivityThread创建Looper使用;
    Looper.getMainLooper()-通过该方法可以在任意地方获取到主线程的Looper;
    Looper.quit() Looper.quitSafely()-退出Looper,自主创建的Looper建议在不使用的时候退出
  4. ActivityThread主线程通过ApplicationThread和AMS进行进程间通信

如果有耗时操作可以考虑使用HandlerThread机制。
创建HandlerThread后必须首先调用start方法,以此来准备子线程需要的Looper对象,之后再创建Handler对象时,才能在构造方法中调用new Handler(handlerThread.getLooper())来使用Looper对象,注意创建的先后顺序。

如果要看源码分析 请参考
https://blog.csdn.net/franky814/article/details/81387000 HandlerThread的使用及原理浅析

IntentService

IntentService 使用工作线程逐一处理所有启动请求。如果你不需要在 Service 中执行并发任务,IntentService 是最好的选择。
IntentService 是一种特殊的 Service ,它继承了 Service 并且它是一个抽象类,因此必须创建它的子类才能使用 IntentService。
IntentService 可用于执行后台耗时的任务,当任务执行后它会自动停止,同时由于 IntentService 是服务的原因,这导致它的优先级比单纯的线程要高很多,比较适合一些高优先级的后台任务。

  • IntentService 是一种特殊的 Service,它继承了 Service 并且它是一个抽象类,因此必须创建它的子类才能够使用 IntentService。
  • 它可用于执行后台耗时任务,当任务执行完成后它会自动停止,在资源不足时,系统会对一些被认为时无用的资源给清理掉,
  • 由于它是 Service 的原因,它的优先级比单纯的线程的优先级高很多,不容易被系统杀死(清理掉),所以它适合执行一些高优先级的后台任务。
  • 在实现上,IntentService 封装了 Handlerhread 和 Handler。
  • 另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,
  • 并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
    IntentService 的使用
    通过前面的源码分析,我们可以看到,最终每个任务的处理都会调用 onHandleIntent(),因此使用 IntentService 也很简单,只需实现 onHandleIntent() 方法,在这里执行对应的后台工作即可。

举个例子:

我们写一个使用 IntentService 实现在子线程下载多张 美女图片 的效果。

/**
 * Description:
 * <br> 使用 IntentService 实现下载
 * <p>
 * <br> Created by shixinzhang on 17/6/8.
 * <p>
 * <br> Email: shixinzhang2016@gmail.com
 * <p>
 * <a  href="https://about.me/shixinzhang">About me</a>
 */

public class DownloadService extends IntentService {
    private static final String TAG = "DownloadService";
    public static final String DOWNLOAD_URL = "down_load_url";
    public static final int WHAT_DOWNLOAD_FINISHED = 1;
    public static final int WHAT_DOWNLOAD_STARTED = 2;

    public DownloadService() {
        super(TAG);
    }

    private static Handler mUIHandler;

    public static void setUIHandler(final Handler UIHandler) {
        mUIHandler = UIHandler;
    }

    /**
     * 这个方法运行在子线程
     *
     * @param intent
     */
    @Override
    protected void onHandleIntent(final Intent intent) {
        String url = intent.getStringExtra(DOWNLOAD_URL);
        if (!TextUtils.isEmpty(url)) {
            sendMessageToMainThread(WHAT_DOWNLOAD_STARTED, "\n " + DateUtils.getCurrentTime() + " 开始下载任务:\n" + url);
            try {
                Bitmap bitmap = downloadUrlToBitmap(url);
                SystemClock.sleep(1000);    //延迟一秒发送消息
                sendMessageToMainThread(WHAT_DOWNLOAD_FINISHED, bitmap);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送消息到主线程
     *
     * @param id
     * @param o
     */
    private void sendMessageToMainThread(final int id, final Object o) {
        if (mUIHandler != null) {
            mUIHandler.sendMessage(mUIHandler.obtainMessage(id, o));
        }
    }

    /**
     * 下载图片
     *
     * @param url
     * @return
     * @throws Exception
     */
    private Bitmap downloadUrlToBitmap(String url) throws Exception {
        HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
        BufferedInputStream in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
        Bitmap bitmap = BitmapFactory.decodeStream(in);
        urlConnection.disconnect();
        in.close();
        return bitmap;
    }
}

在上面的代码中,我们做了以下几件事:

在 onHandleIntent() 中接收任务,开始下载,同时将状态返回给主线程
下载完成后将得到的 Bitmap 通过 Handler 发送到主线程

/**
 * Description:
 * <br> IntentService 调用实例
 * <p>
 * <br> Created by shixinzhang on 17/6/9.
 * <p>
 * <br> Email: shixinzhang2016@gmail.com
 * <p>
 * <a  href="https://about.me/shixinzhang">About me</a>
 */

public class IntentServiceActivity extends AppCompatActivity implements Handler.Callback {

    @BindView(R.id.iv_display)
    ImageView mIvDisplay;
    @BindView(R.id.btn_download)
    Button mBtnDownload;
    @BindView(R.id.tv_status)
    TextView mTvStatus;

    private List<String> urlList = Arrays.asList("https://ws1.sinaimg.cn/large/610dc034ly1fgepc1lpvfj20u011i0wv.jpg",
            "https://ws1.sinaimg.cn/large/d23c7564ly1fg6qckyqxkj20u00zmaf1.jpg",
            "https://ws1.sinaimg.cn/large/610dc034ly1fgchgnfn7dj20u00uvgnj.jpg");    //美女图片地址
    int mFinishCount;   //完成的任务个数

    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intent_service);
        ButterKnife.bind(this);
        DownloadService.setUIHandler(new Handler(this));
    }

    @OnClick(R.id.btn_download)
    public void downloadImage() {
        Intent intent = new Intent(this, DownloadService.class);

        for (String url : urlList) {
            intent.putExtra(DownloadService.DOWNLOAD_URL, url);
            startService(intent);
        }
        mBtnDownload.setEnabled(false);
    }


    @Override
    public boolean handleMessage(final Message msg) {
        if (msg != null) {
            switch (msg.what) {
                case DownloadService.WHAT_DOWNLOAD_FINISHED:
                    mIvDisplay.setImageBitmap((Bitmap) msg.obj);
                    mBtnDownload.setText("完成 " + (++mFinishCount) + "个任务");
                    break;
                case DownloadService.WHAT_DOWNLOAD_STARTED:
                    mTvStatus.setText(mTvStatus.getText() + (String) msg.obj);
                    break;
            }
        }
        return true;
    }
}

Activity 中做了以下几件事:

设置 UI 线程的 Handler 给 IntentService
使用 startService(intent) 启动 IntentService 执行图片下载任务
在 Handler 的 handleMessage 中根据消息类型进行相应处理

一句话总结 IntentService:
优先级比较高的、用于串行执行异步任务、会自尽的 Service。

例子参考
https://blog.csdn.net/u011240877/article/details/72972610

AsyncTask

构建AsyncTask子类的泛型参数

AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承.继承AsyncTask需要指定如下三个泛型参数:

Params:启动任务时输入的参数类型.

Progress:后台任务执行中返回进度值的类型.

Result:后台任务执行完成后返回结果的类型.

.构建AsyncTask子类的回调方法

AsyncTask主要有如下几个方法:

doInBackground:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.

onPreExecute:执行后台耗时操作前被调用,通常用于进行初始化操作.

onPostExecute:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法.通过此方法进行UI的更新.

onProgressUpdate:当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法.通过此方法我们可以知晓任务的完成进度.

.使用AsyncTask的注意事项

① 必须在UI线程中创建AsyncTask的实例.

② 只能在UI线程中调用AsyncTask的execute方法.

③ AsyncTask被重写的四个方法是系统自动调用的,不应手动调用.

④ 每个AsyncTask只能被执行(execute方法)一次,多次执行将会引发异常.

⑤ AsyncTask的四个方法,只有doInBackground方法是运行在其他线程中,其他三个方法都运行在UI线程中,也就说其他三个方法都可以进行UI的更新操作.

AsyncTask 有两个线程池(SerialExecutor 和 THREAD_POOL_EXECUTOR)和一个 Handler(IntentHandler),其中线程池 SerialExecutor 用于任务的排队,而线程池 THREAD_POOL_EXECUTOR 用于真正的执行任务,InternalHandler 用于将执行环境从线程池切换到主线程。
AsyncTask封装了 Thread 和 Handler,通过 AsyncTask 可以更加方便的执行后台任务以及在主线程中访问UI,但是不适合执行特别耗时的后台任务,对于特别耗时的任务来说,还是使用线程池比较好。

Android线程池的使用

线程池的优点

(1)复用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。

(2)能够有效的控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。

(3)能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。

线程池的分类:
最后该介绍一下主角线程池了。它分为四种:

1.FixedThreadPool
定长线程池特点:
①可控制线程最大并发数(线程数固定)
②超出的线程会在队列中等待
使用优势:能够更快的响应外界的请求。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
              0L,TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());
}

2.CachedThreadPool
缓存线程池的特点:
① 线程数无限制
② 没有核心线程,都是非核心线程
优势:比较适合用来执行大量的但是耗时较少的任务。

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                        60L, TimeUnit.SECONDS, 
                new SynchronousQueue<Runnable>());
}

3.ScheduledThreadPool
定时线程池特点:核心线程数量固定、非核心线程数量无限制(闲置时马上回收)

使用场景:用于执行定时任务和具有固定周期的重复任务。

  // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为4
    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
  // 2. 创建好Runnable类线程对象 & 需执行的任务
    Runnable task =new Runnable(){
        public void run(){
           System.out.println("开始执行任务");
         }
      };
    
 // 3. 向线程池提交任务:schedule()
    scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务
    scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后每隔1000ms执任务
 // 4. 关闭线程池
    scheduledThreadPool.shutdown();

4.SingleTreadExecutor
单线程化线程池特点:只有一个核心线程(保证所有任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题)

使用场景:按顺序执行,不需要处理同步的问题。不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等

// 1. 创建单线程化线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

// 2. 创建好Runnable类线程对象 & 需执行的任务
Runnable task =new Runnable(){
 public void run(){
    System.out.println("开始执行任务");
      }
  };

// 3. 向线程池提交任务:execute()
singleThreadExecutor.execute(task);

// 4. 关闭线程池
singleThreadExecutor.shutdown();

Android 中的线程池来源于 Java 中的 Executor,Executor 是一个接口,真正的线程池实现为 ThreadPOOLExecutor。

真正的线程的实现为ThreadPoolExecutor。(ThreadPoolExecutor继承了AbstractExecutorService,AbstractExecutorService是ExecutorService的实现类,ExecutorService继承了Executor接口)。

ThreadPoolExecutor extends AbstractExecutorService implements ExecutorService extends Executor

ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

在这里插入图片描述

  • corePoolSie
    线程池的核心线程数,默认情况下,核心线程会在线程池中一直存活,即使它们处于闲置状态。如果将 ThreadPoolExecutor 的 allowCoreThreadTimeOut 属性设置为 true,那么闲置的核心线程在等待新任务到来时会有超时策略,这个事件间隔由keepAliveTime 所指定,当等待事件超过 keepAliveTime 所指定的时间,核心线程会被终止。

  • maximumPoolSize
    线程池中所能容纳的最大线程数,当活动线程数达到这个数值后,后续的任务会被阻塞。

  • keepAliveTime
    非核心线程闲置是的超时时长,超过这个时长,非核心线程就会被回收。如果将 ThreadPoolExecutor 的 allowCoreThreadTimeOut 属性设置为 true,keepAliveTime 同样会作用于核心线程。

  • unit
    用于指定 keepAliveTime 参数的时间单位,这是一个枚举,常用的有 TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分钟)等。

  • workQueue
    线程池中的任务队列,通过线程池的 execute 方法提交的 Runnable 对象会存储在这个参数中。

  • threadFactory
    线程工厂,为线程池创建新线程的功能。ThreadFactory 是一个接口,它只有一个方法: Thread newThread(Runnable r).

ThreadPoolExecutor 执行任务时大致遵循如下规则:

  1. 如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。
  2. 如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会直接插入到任务队列中排队等待执行。
  3. 如果在步骤2中无法将任务插入到任务队列里,这往往是由于任务队列已满,这个时候如果线程数量未达到线程池规定的最大值,那么会立刻启动一个非核心线程来执行任务。
  4. 如果步骤3中线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor 会调用
    RejectedExecutionHandler 的 rejectedExecution 方法来通知调用者。

线程池有两个执行的方法,分别是submit()和execute(),这两个方法本质的含义是一样的.
在这里插入图片描述
从图上可以看出的,submit()其实还是需要调用execute()去执行任务,而submit()和execute()本质上的不同是submit()将包装好的任务进行了返回
在这里插入图片描述
线程池的使用

/**
 * 线程池封装
 *
 * @author jun.yang
 *         created at 2018/2/26 10:21
 */
public class ThreadPoolManager {
    private static ThreadPoolManager mInstance;

public static ThreadPoolManager getInstance() {
    if (mInstance == null) {
        synchronized (ThreadPoolManager.class) {
            if (mInstance == null) {
                mInstance = new ThreadPoolManager();
            }
        }
    }
    return mInstance;
}
/**
 * 核心线程池的数量,同时能够执行的线程数量
 */
private int corePoolSize;
/**
 * 最大线程池数量,表示当缓冲队列满的时候能继续容纳的等待任务的数量
 */
private int maximumPoolSize;
/**
 * 存活时间
 */
private long keepAliveTime = 1;
private TimeUnit unit = TimeUnit.HOURS;
private ThreadPoolExecutor executor;

private ThreadPoolManager() {
    /**
     * 给corePoolSize赋值:当前设备可用处理器核心数*2 + 1,能够让cpu的效率得到最大程度执行(有研究论证的)
     */
    corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
    //虽然maximumPoolSize用不到,但是需要赋值,否则报错
    maximumPoolSize = corePoolSize;
    executor = new ThreadPoolExecutor(
            //当某个核心任务执行完毕,会依次从缓冲队列中取出等待任务
            corePoolSize,
            //5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
            maximumPoolSize,
            //表示的是maximumPoolSize当中等待任务的存活时间
            keepAliveTime,
            unit,
            //缓冲队列,用于存放等待任务,Linked的先进先出
            new LinkedBlockingQueue<Runnable>(),
            //创建线程的工厂
		//  Executors.defaultThreadFactory(),
            new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
            //用来对超出maximumPoolSize的任务的处理策略
            new ThreadPoolExecutor.AbortPolicy()
    );
}

/**
 * 执行任务
 *
 * @param runnable
 */
public void execute(Runnable runnable) {
    if (executor == null) {
        //线程池执行者。
        //参1:核心线程数;参2:最大线程数;参3:线程休眠时间;参4:时间单位;参5:线程队列;参6:生产线程的工厂;参7:线程异常处理策略
        executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),
			//   Executors.defaultThreadFactory(),
                new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
                new ThreadPoolExecutor.AbortPolicy());
    }
    if (runnable != null) {
        executor.execute(runnable);
    }
}

/**
 * 移除任务
 */
public void remove(Runnable runnable) {
    if (runnable != null) {
        executor.remove(runnable);
    }
}

/**
 * 创建线程的工厂,设置线程的优先级,group,以及命名
 */
private static class DefaultThreadFactory implements ThreadFactory {
    /**
     * 线程池的计数
     */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);

    /**
     * 线程的计数
     */
    private final AtomicInteger threadNumber = new AtomicInteger(1);

    private final ThreadGroup group;
    private final String namePrefix;
    private final int threadPriority;

    DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
        this.threadPriority = threadPriority;
        this.group = Thread.currentThread().getThreadGroup();
        namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        t.setPriority(threadPriority);
        return t;
    }
   }
  }

调用方法

ThreadPoolManager.getInstance().execute(command));
Runnable command =  new Runnable(){
	@Override
	public void run(){
	SystemClock.sleep(2000)
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值