android:Background线程池和UiThread线程池

由来

希望在代码的任何地方,无论是在Ui线程中调用,还是Thread中调用,都能指定Runnable执行的所在的线程池。

Codes

package com.example.androidbackgroundexecuter;

import java.util.concurrent.Executor;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.MessageQueue;

/**
 *
 * @author Zheng Haibo
 * @Web http://www.mobctrl.net
 *
 */
public final class GlobalExecutor implements Executor {

    static final String APP_EXECUTOR = "APP_EXECUTER";

    private final Handler mainHandler;
    private final Handler backgroundHandler;

    public GlobalExecutor() {
        if (!isOnMainThread()) {
            throw new IllegalStateException(
                    "Error!Please init the Executor in the main thread...");
        }
        mainHandler = new Handler(Looper.getMainLooper());
        HandlerThread handlerThread = new HandlerThread(APP_EXECUTOR);
        handlerThread.start();
        backgroundHandler = new Handler(handlerThread.getLooper());
    }

    @Override
    public void execute(final Runnable command) {
        executeInBackground(command, 0);
    }

    /**
     * execute the command in background thread with a delay of {@link #delay}
     *
     * @param command
     */
    public void execute(final Runnable command, int delay) {
        executeInBackground(command, delay);
    }

    /**
     * execute the command in UiThread
     *
     * @param command
     */
    public void executeInUiThread(final Runnable command) {
        mainHandler.post(command);
    }

    /**
     * execute the command in main thread with a delay of {@link #delay}
     *
     * @param command
     */
    public void executeInUiThread(final Runnable command, int delay) {
        mainHandler.postDelayed(command, delay);
    }

    /**
     * execute the command in background thread with a delay of {@link #delay}
     *
     * @param command
     */
    public void executeInBackground(final Runnable command, final int delay) {
        if (isOnMainThread()) {
            executeDelayedAfterIdleUnsafe(command, delay);
        } else {
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    executeDelayedAfterIdleUnsafe(command, delay);
                }
            });
        }
    }

    /**
     * execute the command in background thread
     *
     * @param command
     */
    public void executeInBackground(final Runnable command) {
        executeInBackground(command, 0);
    }

    private boolean isOnMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }

    private void executeDelayedAfterIdleUnsafe(final Runnable task,
            final int delay) {
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                backgroundHandler.postDelayed(task, delay);
                return false;
            }
        });
    }
}

注意,new GlobalExecutor()是需要在主线程。

使用举例

package com.example.androidbackgroundexecuter;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Process;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

    private GlobalExecutor mGlobalExecutor = null;

    private Button btn1;
    private Button btn2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mGlobalExecutor = new GlobalExecutor();
        btn1 = (Button) findViewById(R.id.btn_1);
        btn1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                System.out.println("debug:btn 1 click");
                btn1.setBackgroundColor(Color.BLACK);
                mGlobalExecutor.execute(new Runnable() {

                    @Override
                    public void run() {
                        System.out.println("debug:click1 execute tid = "
                                + Process.myTid() + ",pid=" + Process.myPid());
                    }
                });

                mGlobalExecutor.executeInUiThread(new Runnable() {

                    @Override
                    public void run() {
                        System.out
                                .println("debug: click1 executeInUiThread tid = "
                                        + Process.myTid()
                                        + ",pid="
                                        + Process.myPid());
                    }
                });
            }
        });

        btn2 = (Button) findViewById(R.id.btn_2);
        btn2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                System.out.println("debug:btn 2 click");
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        System.out.println("debug: click2(run) tid = "
                                + Process.myTid() + ",pid=" + Process.myPid());
                        mGlobalExecutor.execute(new Runnable() {

                            @Override
                            public void run() {
                                System.out
                                        .println("debug: click2 run execute in thread- tid = "
                                                + Process.myTid()
                                                + ",pid="
                                                + Process.myPid());
                            }
                        });

                        mGlobalExecutor
                                .executeInUiThread(new Runnable() {

                                    @Override
                                    public void run() {
                                        System.out
                                                .println("debug: click2 run execute in UiThread- tid = "
                                                        + Process.myTid()
                                                        + ",pid="
                                                        + Process.myPid());
                                        btn1.setBackgroundColor(Color.RED);
                                    }
                                });

                    }
                }).start();
            }
        });
    }
}

Print

相继点击按钮btn1和btn2,日志如下:

05-20 10:25:49.045: I/System.out(3144): debug:btn 1 click
05-20 10:25:49.115: I/System.out(3144): debug: click1 executeInUiThread tid = 3144,pid=3144
05-20 10:25:49.125: I/System.out(3144): debug:click1 execute tid = 3157,pid=3144
05-20 10:25:50.105: I/System.out(3144): debug:btn 2 click
05-20 10:25:50.105: I/System.out(3144): debug: click2(run) tid = 3582,pid=3144
05-20 10:25:50.145: I/System.out(3144): debug: click2 run execute in UiThread- tid = 3144,pid=3144
05-20 10:25:50.175: I/System.out(3144): debug: click2 run execute in thread- tid = 3157,pid=3144

优点

我们可以在任意线程中调用我们想执行的Runnable,非常方便。

更多交流

Android开发联盟QQ群:272209595

时间: 2024-07-29 01:17:40

android:Background线程池和UiThread线程池的相关文章

Android 多线程下载,断点续传,线程池

你可以在这里看到这个demo的源码: https://github.com/onlynight/MultiThreadDownloader 效果图 这张效果图是同时开启三个下载任务,限制下载线程数量的效果图. 多线程下载原理 多线程下载的原理就是将下载任务分割成一个个小片段再将每个小片段分配给各个线程进行下载. 例如一个文件大小为100M,我们决定使用4个线程下载,那么每个线程下载的大小即为25M,每个线程的起始以及结束位置依次如下: 0: 0-25M 1: 25-50M 2: 50-75M 3

Android线程管理之ExecutorService线程池(二)

前言: 上篇学习了线程Thread的使用,今天来学习一下线程池ExecutorService. 为什么要引入线程池? 1.)new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源导致系统瘫痪. 不利于扩展,比如如定时执行.定期执行.线程中断 2.)采用线程池的优点 重用存在的线程,减少对象创建.消亡的开销,性能佳 可有效控制最大并发线程数,提高系统资源的使用率,同

Android 线程池来管理线程

网上讲了很多的关于线程池的例子.其实在我们实际应用中,譬如说,一个应用的线程是怎样来管理的,我们就可以说,我们可以使用线程池来管理线程. eg: class DianLiang1 implements Runnable { @Override punlic void Run{ system.println("*************111111111111111111111****************"); } } class DianLiang2 implements Runn

黑马程序员——JAVA基础之Day24 多线程 ,死锁,线程间通信 ,线程组,线程池,定时器。

------- android培训.java培训.期待与您交流! ---------- Lock()实现提供了比使用synchronized方法和语句可获得更广泛的锁定操作. private Lock lock =new ReentrantLock(); 被锁的代码要用   lock.lock()                lock.unlock()    包括.其中用try   ...finally包围 同步:效率低,如果出现同步嵌套,会出现死锁.  但是安全. 死锁问题:两个或者两个以上

线程的控制和线程池

一.WaitHandle: ”.Net 中提供了一些线程间更自由通讯的工具,他们提供了通过"信号"进行通讯的机制 可以通过ManualResetEvent,AutoResetEvent(他是在开门并且一个 WaitOne 通过后自动关门)来进行线程间的通讯 waitOne:    等待开门 Set:           开门 Reset:       关门 static void Main(string[] args) { ManualResetEvent mre = new Manu

线程池中的线程的排序问题

1 package org.zln.thread.poolqueue; 2 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 6 import java.util.Comparator; 7 import java.util.UUID; 8 import java.util.concurrent.*; 9 10 /** 11 * 线程池中的线程的排序问题 12 * Created by sherry on 16/11/4

深入浅出 Java Concurrency (33): 线程池 part 6 线程池的实现及原理 (1)[转]

线程池数据结构与线程构造方法 由于已经看到了ThreadPoolExecutor的源码,因此很容易就看到了ThreadPoolExecutor线程池的数据结构.图1描述了这种数据结构. 图1 ThreadPoolExecutor 数据结构 其实,即使没有上述图形描述ThreadPoolExecutor的数据结构,我们根据线程池的要求也很能够猜测出其数据结构出来. 线程池需要支持多个线程并发执行,因此有一个线程集合Collection<Thread>来执行线程任务: 涉及任务的异步执行,因此需要

Java多线程系列--“JUC线程池”03之 线程池原理(二)

线程池示例 在分析线程池之前,先看一个简单的线程池示例. import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadPoolDemo1 { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThre

Java多线程系列--“JUC线程池”05之 线程池原理(四)

拒绝策略介绍 线程池的拒绝策略,是指当任务添加到线程池中被拒绝,而采取的处理措施.当任务添加到线程池中之所以被拒绝,可能是由于:第一,线程池异常关闭.第二,任务数量超过线程池的最大限制. 线程池共包括4种拒绝策略,它们分别是:AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy和DiscardPolicy. AbortPolicy -- 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常. Calle