【发布时间】:2013-11-13 12:49:29
【问题描述】:
在Android中,公共类中的全局变量或在线程中声明它有什么好处?
我从
a very good Thread,这里每次触发线程时都会声明String updateWords。
那么,这会影响内存吗?
我声明不。变量,所以,我在问。
任何帮助将不胜感激。 谢谢。
【问题讨论】:
标签: java android multithreading global-variables
在Android中,公共类中的全局变量或在线程中声明它有什么好处?
我从
a very good Thread,这里每次触发线程时都会声明String updateWords。
那么,这会影响内存吗?
我声明不。变量,所以,我在问。
任何帮助将不胜感激。 谢谢。
【问题讨论】:
标签: java android multithreading global-variables
您应该只在替代方案非常糟糕时才使用全局变量。
启动线程比创建对字符串的引用要贵 1000 倍。如果您担心使用单个字符串,甚至是少量字符串,则根本不应该创建线程。
即使你有几千个字符串,它们也会像使用局部变量一样使用与全局变量相同的内存量。唯一的区别是全局变量使用堆,而局部变量使用堆栈和堆,大部分使用仍在堆上。
【讨论】:
String var 的成本。另外,Java 中的 String 文字实际上无论如何都变成了单个值。我认为你打破了一个好的模式,几乎没有收获。
良好的面向对象编程通常回避“全局”变量,而是倾向于将变量封装在对象中。有时这可以打破,比如当你有常量或其他东西时,但有一些模式。
也就是说,是的,如果您要创建多个线程,每个线程都有自己的updateWords,那么您将创建更多对象,从而进行更多垃圾回收。但是,由于updateWords 是一个字符串,如果它在所有线程中设置为相同的值,Java 应该只创建一个String,因为Strings 在 Java 中是字面量。
【讨论】:
创建一个公共静态属性,并像这样在 Main Class 上初始化:
public class foo {
public static final string name = "Stack Overflow";
}
【讨论】:
只要线程没有被破坏,内存就会被消耗。查看字符串是否是您的类的属性(根据面向对象的设计)。
【讨论】:
Java(和其他语言)中有几个内存区域用于各种任务。
最昂贵的是堆内存,基本上使用new 关键字创建的所有内容都进入堆。
然后是堆栈,可以说是一个本地“堆”,但没有与创建堆变量相关的大部分成本,因此速度更快。几乎所有像updateWords 这样的局部变量都位于堆栈中。
寄存器是速度极快的处理器内部变量。 JVM 优化器总是会在合适的时候尝试将内容放入内部寄存器,但由于寄存器的数量非常有限,所以只有非常常用的变量才会放在那里。
但昂贵意味着堆和寄存器之间的执行时间差为 0.0000000001 秒。
那么你应该知道在声明一个本地字符串或任何对象时你实际保留的是什么:一个指针。实际上是一个 32/64 位“整数”,它保存实际找到字符串/对象的地址。因此,String updateWords = updateAuto(); 指令将不会创建新字符串,也不会将其复制到任何地方,所发生的只是 updateAuto() 函数返回一个指针(“整数”)并将 updateWords 设置为该值。这与编写int updateWords = 42 一样快,并且完全在堆栈甚至寄存器上完成,如果优化器愿意的话。
通常,与内存的内部组织方式相比,您应该更关心可见性以及最方便/对您的应用程序产生最少错误的方式。一次手动优化通常会使您的应用程序速度提高不超过 0.0000001%,其次在保留内存时唯一愚蠢的做法是在这样的循环中毫无意义地进行:
for (int i = 0; i < 1000; ++i) {
new MyReallyStupidMemoryWastingObject();
}
但即使这样,垃圾收集器也会优雅地处理(只要您不通过将所有这些指针放在列表或类似的东西中来保存所有这些指针)。
因此:如果可以简化代码,尤其是减少错误,请使用全局变量。示例是全局常量,如枚举或广泛使用的字符串关键字。否则使用本地或类本地变量并依赖 JVM 来正确执行操作。
一个常见的事情是用final这个词给JVM一个使用提示。这允许 JVM 对此变量进行全面优化,甚至通过将其放入寄存器来完全删除它,因为它知道您永远不会更改它。
【讨论】: