当前位置: 首页 > 编程笔记 >

Android中创建多线程管理器实例

柳豪
2023-03-14
本文向大家介绍Android中创建多线程管理器实例,包括了Android中创建多线程管理器实例的使用技巧和注意事项,需要的朋友参考一下

如果你要反复执行一个任务,用不同的数据集(参数不同),但一次只要一个执行(任务是单线程的),IntentService符合你的需求。当需要在资源可用时自动执行任务,或允许多任务同时执行,你需要一个线程管理器管理你的线程。ThreadPoolExecutor,会维护一个队列,当它的线程池有空时,从队列里取任务,并执行。要运行任务,你要做的就是把它加到队列里。

线程池可以并联运行一个任务的多个实例,所以你要保存代码线程安全。能被多线程访问的变量需要同步块.更多信息,见Processes and Threads(http://developer.android.com/guide/components/processes-and-threads.html)

定义线程池类

在它自己类中实例ThreadPoolExecutor.在类里,如下操作:

为线程池使用static变量

你可能在app里只需要一个单例的线程池,这是为了统一控制限制CPU或网络资源。如果你有不同的Runnable类型,你可能想要每种类型都有各自的线程池,但这些都可以放到一个单一的实例里。比如,你可以把它声明成全局变量:


public class PhotoManager {

    ...

    static  {

        ...

        // Creates a single static instance of PhotoManager

        sInstance = new PhotoManager();

    }

    ...

使用private构造方法

把构造方法声明成private,可以确保单例,这意味着你不需要在同步代码块里封装类访问。


 public class PhotoManager {

        ...

        /**

         * 构建用来下载和decode图片的工作队列和线程池,因为构造方法标记为private,

         * 对其他类不可访问(甚至同包下的类)

         */

        private PhotoManager() {

            ...

        }

调用线程池类里的方法来开始任务

线程池类里定义一个方法,用来添加任务到线程池队列,如:


public class PhotoManager {

    ...

    // 供PhotoView调用获取图片

    static public PhotoTask startDownload(

        PhotoView imageView,

        boolean cacheFlag) {

        ...

        // 添加一个任务到线程池

        sInstance.

                mDownloadThreadPool.

                execute(downloadTask.getHTTPDownloadRunnable());

        ...

    }

实例化一个UI线程的Handler.

Handler用于与UI线程通讯,大多数UI控件只允许在UI线程修改。


private PhotoManager() {

    ...

        // Defines a Handler object that's attached to the UI thread

        mHandler = new Handler(Looper.getMainLooper()) {

            /*

             * handleMessage() defines the operations to perform when

             * the Handler receives a new Message to process.

             */

            @Override

            public void handleMessage(Message inputMessage) {

                ...

            }

        ...

        }

    }

判断线程池参数

一旦你有了全部类结构,你就可以开始定义线程池。实例化一个线程池对象,你需要下面的值:
初始池大小,最大池大小。
线程池的线程数量主要依赖于设备的CPU核心数.可以从系统环境中获取。


public class PhotoManager {

...

    /*

     * Gets the number of available cores

     * (not always the same as the maximum number of cores)

     */

    private static int NUMBER_OF_CORES =

            Runtime.getRuntime().availableProcessors();

}

这个数字可能不能反映出设备的物理cpu内核数量;某些设备CPU会根据系统负载自动禁用部分内核,对于这些设备,availableProcessors()返回的是当前活跃的内核数量。

保持活跃时间和时间单位

一个进程在关闭前,保持空闲状态的时间(可以复用进程)。时间单位在TimeUnit里

任务队列

ThreadPoolExecutor的列队保存Runnable对象。在线程中执行代码,线程池管理器会从一个FIFO队列里取出一个Runnable对象,附加到线程里。队列实现BlockingQueue接口,在创建线程池时提供。你可以从现有实现中选一个,适应你的需求,参见ThreadPoolExecutor。下面是使用LinkedBlockingQueue的例子:


public class PhotoManager {

    ...

    private PhotoManager() {

        ...

        // A queue of Runnables

        private final BlockingQueue<Runnable> mDecodeWorkQueue;

        ...

        // Instantiates the queue of Runnables as a LinkedBlockingQueue

        mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();

        ...

    }

    ...

}

创建线程池

调用ThreadPoolExecutor()方法初始化线程池。它会创建管理线程。因为线程池的初始大小和最大池大小是一样的,ThreadPoolExecutor在初始化时就创建了所有线程对象,如:

    private PhotoManager() {

        ...

        // Sets the amount of time an idle thread waits before terminating

        private static final int KEEP_ALIVE_TIME = 1;

        // Sets the Time Unit to seconds

        private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;

        // Creates a thread pool manager

        mDecodeThreadPool = new ThreadPoolExecutor(

                NUMBER_OF_CORES,       // Initial pool size

                NUMBER_OF_CORES,       // Max pool size

                KEEP_ALIVE_TIME,

                KEEP_ALIVE_TIME_UNIT,

                mDecodeWorkQueue);

    }

 类似资料:
  • 服务器实例是运行在云中的虚拟机。用户可以通过下面几个资源创建一个新的实例。 上传到OpenStack的镜像。 复制到persistent volume中的镜像。该volume须是由cinder-volumn通过iSCSI提供的。实例可以在该volume上启动。 创建实例 如果要从volume中创建实例,请参考如下步骤: 在选择在哪一个volume上启动时,先在这个volume中选择任意一个imag

  • 问题内容: 我正在使用Callable接口在serviceImpl中编写多线程程序。我正在使用spring事务管理器。在DB中执行更新操作时,它会成功执行。但是更新后的数据不会反映在DB中。但是,当我运行不带多线程的程序时,它将在DB中更新。 这是我的配置 我可以转向事务管理器的另一种方法。只是我想确认这种方法是否支持多线程。所以我的问题是 spring事务管理器是否支持多线程(我的意思是仅通过声

  • 如果我有一个固定大小的线程池,它什么时候真正调用启动线程?(它会在创建时启动它们吗?还是等到我开始提交任务时再启动?)

  • 本文向大家介绍java 线程创建多线程详解,包括了java 线程创建多线程详解的使用技巧和注意事项,需要的朋友参考一下 Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类。 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: Tread thread = new Thread(); thread.sta

  • Spring Transaction不支持多线程,所以我尝试在thread的run()方法中手动管理事务。但是,没用! 我想在下面的示例中回滚每个线程的run()方法,当其中有异常抛出时。(在以下情况下,插入到UNKNOWN_TABLE) 我的预期结果是“开始,1,3,5,结束”。 而实际结果是‘开始,1,2,3,4,5,结束’。 欢迎任何回复!谢谢! 主要类别: 服务等级:

  • BilledLines=Integer.ParseInt(args[7]); Array=TaxCalc.Calculation(输入,y,BilledLines,); 返回数组; } taxouput函数是OSB中的多线程函数。现在,我想调用setup()和 cleanup(),以便setup()只对第一个线程调用,而 cleanup()只对最后一个线程调用。