安卓线程Runnable性能

5

我想了解启动可运行线程的两种不同方法的性能和CPU / RAM要求。

我有一些代码,每10毫秒收集传感器数据,并将值插入到后台线程中的数据库中(使用单个线程执行器)。 Executor服务的创建方式如下:

executor = Executors.newSingleThreadExecutor();

其中一种方法是像这样做...

public void onSensorChanged(SensorEvent event) {
    //get sensor values

    //insert into database
    executor.execute(new Runnable(){
        //database insert code here
    });
}

我在很多教程中看到了这种方法,但由于我每10ms就要执行一次,感觉它会占用很多资源,因为每当检测到传感器值变化时,我就会创建一个新对象。这个新对象每10ms是否会被覆盖?或者随着新对象的创建,它是否会占用越来越多的RAM?

后来我重构了我的代码,使其更像这样:

executor = Executors.newSingleThreadExecutor();
myRunnable = new MyRunnable();

class MyRunnable implements Runnable {
    public void run() {
        //database insert code here
    }
}

public void onSensorChanged(SensorEvent event) {
    //get sensor values

    //insert into database
    executor.execute(myRunnable);
}

我认为只需实例化一个对象一次,而不是每次传感器变化时都这样做。我的想法正确吗?相比之前的方法,这种方式使用的RAM更少吗?有没有更高效/更好的方法来完成这个任务?


在我的第二个示例中,我认为我只创建了一个后台线程可运行对象?也许我误解了您的意思,但我认为executor.execute()是将任务添加到队列中,每个排队的任务都在执行保存操作? - Simon
是的,您理解得很正确。我想您提供的第二个示例将会奏效,但前提是您需要正确同步共享数据(我的意思是您省略的代码中,从传感器接收到的事件要被存储在某个对象中,然后由写入程序读取)。 - Alex Salauyou
在第一个例子中,您直接将需要保存的数据放入了“Runnable”中。在第二个例子中,您无法这样做,因为“event”在“MyRunnable”中不可见。因此,您需要另一个中间对象,在将“SensorEvent”对象(或派生对象)保存到数据库之前存储它们。我建议使用队列作为生产者-消费者任务的最常见模式。 - Alex Salauyou
有趣。在我的第二种方法中,我有一个初始为空的浮点数数组。在onSensorChanged期间,我将传感器值收集为一个数组,并替换该初始浮点数数组。因此,该数组每10毫秒就会被最新值覆盖。然后,MyRunnable类只需获取该数组的值并插入数据库。 - Simon
1
@Simon 如果您使用单个数组来存储数据,那么您应该同步访问它--以确保编写者始终看到一致的值。回答您关于内存消耗的问题:成为无引用对象的对象会很快被GC清除,内存变得可用--所以您根本不需要担心它,除非您处理需要长时间可见的大型对象,例如图像、位图、共享大型数据等(不是您的情况)。 - Alex Salauyou
显示剩余7条评论
1个回答

2

每10毫秒创建一个新的Runnable实例肯定会导致垃圾收集器更频繁地运行,可能会影响应用程序的性能。我认为你的第二种方法更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接