Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 短而频繁的作业:HandlerThread还是ThreadPoolExecutor?_Java_Android_Multithreading - Fatal编程技术网

Java 短而频繁的作业:HandlerThread还是ThreadPoolExecutor?

Java 短而频繁的作业:HandlerThread还是ThreadPoolExecutor?,java,android,multithreading,Java,Android,Multithreading,首先,我无法确定标题应该是什么,所以如果不够具体,问题本身就是 我们有一个应用程序,它使用前台服务并永远保持活动状态,在这个服务中,需要在后台线程上运行频繁的数据库访问作业、网络访问作业等。一项工作本身消耗的时间很少,但工作本身是频繁的。显然,它们需要在工作线程上运行,所以我在这里询问我们应该遵循哪种设计 是一种结构,它创建单个线程并使用队列执行任务,但始终循环并等待消耗电源的消息,同时为每个作业创建多个线程并在作业完成时删除线程,但由于线程太多,可能会出现泄漏,甚至内存不足。作业计数可以是5,

首先,我无法确定标题应该是什么,所以如果不够具体,问题本身就是

我们有一个应用程序,它使用前台服务并永远保持活动状态,在这个服务中,需要在后台线程上运行频繁的数据库访问作业、网络访问作业等。一项工作本身消耗的时间很少,但工作本身是频繁的。显然,它们需要在工作线程上运行,所以我在这里询问我们应该遵循哪种设计

是一种结构,它创建单个线程并使用队列执行任务,但始终循环并等待消耗电源的消息,同时为每个作业创建多个线程并在作业完成时删除线程,但由于线程太多,可能会出现泄漏,甚至内存不足。作业计数可以是5,也可以是20,这取决于用户以某种方式的行为。而且,两份工作之间可能有5秒的间隔,或者一天的间隔,完全取决于用户。但是,请记住,应用程序将永远保持活动状态,并等待这些作业执行


那么,对于这个特定的场合,哪一个更适合使用呢?线程池执行器还是处理程序线程?非常感谢您的建议。

不要真的认为这是您正在运行的线程数量的问题,更多的是您希望它们如何运行。如果希望它们一次运行一个(即,一次只希望对数据库查询执行),则使用
HandlerThread
。如果需要多线程/线程池,请使用和
Executor

根据我的经验,泄漏更多地取决于线程的编码方式,而不是所选择的实现


就我个人而言,我会使用
HandlerThread
,这里有一篇关于实现它们以及如何避免内存泄漏的好文章

警告:我不做Android工作,所以我不是这方面的专家。我的观点基于对Android文档的快速阅读

tl;博士 ➥ 使用执行器而不是
HandlerThread

Executors框架比
HandlerThread
使用的传统
Thread
工具更现代、更灵活、更强大。在HandlerThread中你能做的一切都可以在执行者身上做得更好

分歧 和之间的一大区别是第一个来自Android,而第二个来自Java。因此,如果要用Java做其他工作,您可能不想养成使用
HandlerThread
的习惯

另一个很大的区别是年龄。
android.os.HandlerThread
类继承自
java.lang.Thread
,可以追溯到最初的android API级别1。Java中的
线程
功能在设计上是有限的,尽管它的时间很好。在后来的Java中,这种功能被更现代、更灵活、更强大的功能所取代

遗嘱执行人 您的问题不清楚这些是重复性工作还是临时安排的工作。任何一个都可以由执行人处理

对于在特定时间运行一次的作业和定期计划作业,请使用。您可以通过指定延迟、等待执行的时间跨度来安排作业在特定时间运行一次。对于重复作业,可以指定等待、运行、等待、运行的数量,依此类推。我不会进一步讨论这个问题,因为您似乎在谈论零星的即时作业,而不是计划或重复作业。如果感兴趣,可以搜索堆栈溢出,因为在堆栈溢出上已多次涉及ScheduledExecutorService

单线程池 HandlerThread是创建单个线程的结构

如果要重新创建该单线程行为,请使用

把你的任务做好。通过lambda语法或常规语法,实现或使用(a)实现任一接口的类,(b)不定义类

Runnable sayHelloJob = new Runnable()
{
    @Override
    public void run ( )
    {
        System.out.println( "Hello. " + Instant.now() );
    }
};
常规语法

Runnable sayHelloJob = new Runnable()
{
    @Override
    public void run ( )
    {
        System.out.println( "Hello. " + Instant.now() );
    }
};
Lambda语法

Runnable sayBonjourJob = ( ) -> System.out.println( "Bonjour. " + Instant.now() );
向executor service提交任意数量的作业

es.submit( sayHelloJob ) ;
es.submit( sayBonjourJob ) ;
请注意,
submit
方法返回一个。使用该
Future
对象,您可以检查计算是否完成、等待其完成或检索计算结果。或者,您可以选择忽略上面代码中显示的
Future
对象

固定线程池 如果需要多线程行为,只需使用不同类型的线程池创建执行器

ExecutorService es = Executors.newCachedThreadPool() ;
为单个提交作业队列(可运行的或可调用的对象)提供服务的线程数最大。这些线程将继续工作,并在出现故障时根据需要进行更换

ExecutorService es = Executors.newFixedThreadPool​( 3 ) ;  // Specify number of threads.
代码的其余部分保持不变。这就是使用
ExecutorService
接口的好处:您可以更改executor服务的实现,以获得不同的行为,同时不破坏调用该executor服务的代码

缓存线程池 您的需求可能会得到更好的服务。与固定线程池那样立即创建和维护一定数量的线程不同,该线程池只在需要时创建线程,最多创建一个线程。当一个线程完成并静止超过一分钟时,线程终止。正如Javadoc所指出的,这非常适合“许多短期异步任务”,比如您的任务。但请注意,可能同时运行的线程没有上限。如果您的应用程序的性质是,您可能会经常看到许多作业同时到达,那么您可能希望使用不同的实现,而不是缓存线程池

ExecutorService es = Executors.newCachedThreadPool() ;
管理执行器和线程 但是由于线程太多,可能会出现泄漏,甚至内存不足

程序员和系统管理员的工作就是不让生产服务器负担过重。您需要监控生产中的性能。管理很简单