Heim  >  Artikel  >  Java  >  Einige Dinge, die „aus Leistungsgründen“ bei der Java-Programmierung getan werden sollten

Einige Dinge, die „aus Leistungsgründen“ bei der Java-Programmierung getan werden sollten

伊谢尔伦
伊谢尔伦Original
2016-11-29 10:46:26901Durchsuche

Der aktuelle Maschinenspeicher ist wieder voll, wir sollten auch unseren Code überprüfen. Diese schlechten Gewohnheiten oder mangelndes Verständnis für Programmiersprachen sollten berücksichtigt werden überprüft. Unterdrückt und unterdrückt.

Einige Dinge, die „aus Leistungsgründen“ bei der Java-Programmierung getan werden sollten

Im Folgenden sind einige Dinge aufgeführt, die in der Java-Programmierung so weit wie möglich getan werden sollten, zusammengefasst unter Bezugnahme auf Online-Ressourcen.

 1. Versuchen Sie, Singletons in geeigneten Situationen zu verwenden

Die Verwendung von Singletons kann die Last reduzieren, die Ladezeit verkürzen und die Ladeeffizienz verbessern, ist jedoch nicht überall für Singletons geeignet Vereinfacht ausgedrückt sind Singletons hauptsächlich auf die folgenden drei Aspekte anwendbar:

Erstens: Steuern Sie die Ressourcennutzung und den gleichzeitigen Zugriff auf Ressourcen durch Thread-Synchronisierung.

Zweitens: Kontrolle Die Generierung von Instanzen, um den Zweck der Ressourceneinsparung zu erreichen;

Drittens: Kontrolle des Datenaustauschs, wodurch die Kommunikation zwischen mehreren unabhängigen Prozessen oder Threads ermöglicht wird, ohne eine direkte Verbindung herzustellen.

 2. Versuchen Sie, die Verwendung statischer Variablen nach Belieben zu vermeiden

Sie müssen wissen, dass gc normalerweise nicht den von diesem Objekt belegten Speicher zurückgewinnt, wenn ein Objekt als referenzierte statische Variable definiert ist, z as

public class A{
static B b = new B();
}

Zu diesem Zeitpunkt ist der Lebenszyklus der statischen Variablen b mit Klasse A synchronisiert. Wenn Klasse A nicht entladen wird, verbleibt Objekt b im Speicher, bis das Programm beendet wird.

 3. Versuchen Sie zu vermeiden, zu oft zu viele Java-Objekte zu erstellen

Versuchen Sie, neue Objekte in häufig aufgerufenen Methoden und Schleifen zu vermeiden, da das System nicht nur Zeit zum Erstellen von Objekten benötigt, sondern auch Zeit Die Zeit, diese Objekte zu sammeln und zu verarbeiten, und die Objekte im größtmöglichen Umfang wiederzuverwenden, der innerhalb unserer Kontrolle liegt. Es ist am besten, die Objekte durch grundlegende Datentypen oder Arrays zu ersetzen.

4. Versuchen Sie, den endgültigen Modifikator zu verwenden.

Klassen mit dem endgültigen Modifikator können nicht abgeleitet werden. In der Java-Kern-API gibt es viele Beispiele für die Anwendung von final, z. B. java.lang.String. Durch die Angabe von final für die String-Klasse wird verhindert, dass Benutzer die Methode length() überschreiben. Wenn eine Klasse außerdem final ist, sind alle Methoden der Klasse final. Der Java-Compiler sucht nach Möglichkeiten, alle endgültigen Methoden zu integrieren (dies hängt von der jeweiligen Compiler-Implementierung ab). Dadurch kann die Leistung um durchschnittlich 50 % verbessert werden.

5. Versuchen Sie, lokale Variablen zu verwenden

Die beim Aufruf der Methode übergebenen Parameter und die während des Aufrufs erstellten temporären Variablen werden im Stapel (Stack) gespeichert, was schneller ist. Andere Variablen wie statische Variablen, Instanzvariablen usw. werden im Heap erstellt und sind langsamer.

 6. Versuchen Sie, mit den Verwendungssituationen sowohl der Verpackungstypen als auch der Grundtypen umzugehen

Obwohl Verpackungstypen und Grundtypen während der Verwendung ineinander umgewandelt werden können, ist der von ihnen erzeugte Speicher der Bereich ist völlig anders. Die Basistypdaten werden auf dem Stapel generiert und verarbeitet. Der Wrapper-Typ ist ein Objekt und eine Instanz wird auf dem Heap generiert.

In Sammlungsklassenobjekten eignen sich Verpackungstypen für die Verarbeitung, für die Objekte erforderlich sind. Für andere Verarbeitungen wird die Verwendung von Basistypen empfohlen.

 7. Verwenden Sie die Synchronisierung mit Vorsicht und minimieren Sie die Synchronisierungsmethoden

Wir alle wissen, dass das Erreichen der Synchronisierung einen hohen System-Overhead erfordert und sogar zu Deadlocks führen kann. Versuchen Sie daher, unnötige Synchronisierungen zu vermeiden Kontrolle. Wenn die Synchronisierungsmethode aufgerufen wird, wird das aktuelle Objekt direkt gesperrt, und andere Threads können keine anderen Methoden des aktuellen Objekts aufrufen, bis die Methode ausgeführt wird. Daher sollte die Synchronisierungsmethode so klein wie möglich sein und die Methodensynchronisierung sollte so weit wie möglich anstelle der Codeblocksynchronisierung verwendet werden.

8. Versuchen Sie, StringBuilder und StringBuffer für die String-Verbindung zu verwenden

Ich werde nicht näher darauf eingehen.

9. Versuchen Sie, die Finalisierungsmethode nicht zu verwenden

Tatsächlich ist es eine sehr schlechte Wahl, die Ressourcenbereinigung in der Finalisierungsmethode abzuschließen, da die GC-Arbeitsbelastung hoch ist, insbesondere das Recycling von Young When Wenn der Speicher generiert wird, führt dies häufig dazu, dass die Anwendung angehalten wird. Die Verwendung der Finalisierungsmethode zum Bereinigen von Ressourcen führt daher zu einer größeren Belastung des GC und einer schlechteren Effizienz des Programmbetriebs.

10. Versuchen Sie, grundlegende Datentypen anstelle von Objekten zu verwenden

String str = "hello";

Die obige Methode erstellt einen „Hallo“-String und die JVM Der Zeichen-Cache-Pool speichert auch diese Zeichenfolge zwischen.

String str = new String("hello"); str Enthält auch ein char[]-Array, das h, e, l, l, o

der Reihe nach speichert. 11. Einzelne Threads sollten versuchen, HashMap, ArrayList

HashTable, Vector, zu verwenden. usw. Es wird ein Synchronisationsmechanismus verwendet, der die Leistung verringert.

12. Erstellen Sie HashMap so vernünftig wie möglich

Wenn Sie eine größere HashMap erstellen möchten, nutzen Sie einen anderen Konstruktor vollständig

public HashMap(int initialCapacity, float loadFactor )

Vermeiden Sie mehrere Hash-Rekonstruktionen. Standardmäßig beträgt die anfängliche Kapazität nur 16 und der Lastfaktor beträgt genau 0,75 die optimale Größe, die Sie benötigen. Dasselbe gilt für Hashtable und Vektoren.

 13. Wiederholte Berechnung von Variablen minimieren

  如

  for(int i=0;i

  应该改为

  for(int i=0,len=list.size();i

  并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 

  14. 尽量避免不必要的创建

  如

  A a = new A();

  if(i==1){list.add(a);}

  应该改为

  if(i==1){

  A a = new A();

  list.add(a);}

  15. 尽量在finally块中释放资源

  程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。 

  16. 尽量使用移位来代替'a/b'的操作

  "/"是一个代价很高的操作,使用移位的操作将会更快和更有效

  如

  int num = a / 4;

  int num = a / 8;

  应该改为

  int num = a >> 2;

  int num = a >> 3;

  但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解

  17.尽量使用移位来代替'a*b'的操作

  同样的,对于'*'操作,使用移位的操作将会更快和更有效

  如

  int num = a * 4;

  int num = a * 8;

  应该改为

  int num = a

  int num = a

  18. 尽量确定StringBuffer的容量

  StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再 丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。 

  如:StringBuffer buffer = new StringBuffer(1000);  

  19. 尽量早释放无用对象的引用

  大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。

  例如:

Public void test(){
Object obj = new Object();
……
Obj=null;
}

上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:

Public void test(){
Object obj = new Object();
……
Obj=null;
//执行耗时,耗内存操作;或调用耗时,耗内存的方法
……
}

这时候就有必要将obj赋值为null,可以尽早的释放对Object对象的引用。

  20. 尽量避免使用二维数组

  二维数据占用的内存空间比一维数组多得多,大概10倍以上。

  21. 尽量避免使用split

  除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需 要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。

  22. ArrayList & LinkedList

  一 个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指 针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2 者得数据结构,对症下药。

  23. 尽量使用System.arraycopy ()代替通过来循环复制数组

  System.arraycopy() 要比通过循环来复制数组快的多 

  24. 尽量缓存经常使用的对象

  尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。

  25. 尽量避免非常大的内存分配

  有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。

  26. 慎用异常

  当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。

  如果您创建一个 Exception ,就得付出代价。好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,您甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常。幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就 抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。

相关回复:

  xuanyuan 写道

  7.慎用synchronized,尽量减小synchronize的方法

  re:同意,不过文中有个地方说错了,使用synchronized关键字并不一定都是锁定当前对象的,要看具体的锁是什么。如果是在方法上加的synchronized,则是以对象本身为锁的,如果是静态方法则锁的粒度是类。

  ---------------

  9.尽量不要使用finalize方法

  re:同意,其实不推荐用finalize方法的根本原因在于,JVM的规范并不保证何时执行该方法,所以用这个方法来释放资源很不合适,有可能造成长时间资源得不到释放。

  ---------------

  16.尽量使用移位来代替'a/b'的操作;17.尽量使用移位来代替'a*b'的操作

  re:个人不太同意这两条。这样做确实有更好的性能,但是却牺牲了可读性。这两个操作符对很多程序员来说并不直观。我认为在如今硬件价格不那么昂贵的情况下,略微牺牲一些性能,换来更好的可读性和可维护性是好的选择。

  wuzhengju 写道

19.尽量早释放无用对象的引用

  大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。

  例如:

Public void test(){
Object obj = new Object();
……
Obj=null;
}

上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:

Public void test(){
Object obj = new Object();
……
Obj=null;
//执行耗时,耗内存操作;或调用耗时,耗内存的方法
……
}

如果Object obj = new Object(); 如果这对象并不是大对象,这有必要吗?Obj=null;只是告诉jvm这个对象已经成为垃圾,至于什么时候回收,还不能确定! 这可读性也不好!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn