By using some assistive tools to find bottlenecks in the program, you can then optimize the code in the Bottleneck section. There are generally two scenarios: optimizing code or changing design methods. We generally choose the latter because it is better to improve the performance of the program than to call some optimized code without calling the following code. A well-designed program can streamline the code and improve performance.
Here are some of the methods and techniques that are often used in the design and coding of Java programs in order to improve the performance of Java programs.
1. The creation and resizing of objects.
A common problem in Java programming is the lack of proper use of the functions provided by the Java language itself, which often results in a large number of objects (or instances). Because the system not only takes time to generate objects, it may take time for them to be garbage collected and processed later. Therefore, generating too many objects will have a significant impact on the performance of the program.
Example 1: About String, stringbuffer,+ and append
The Java language provides operations on variables of type string. But if used improperly, it will affect the performance of the program. As in the following statement:
String name=New string ("Huangweifeng"); SYSTEM.OUT.PRINTLN (name+ "is my Name");
The
seems to have been very streamlined, but it is not. In order to generate the binary code, the following steps and actions are performed:
(1) generate a new string new string (str_1);
(2) Copy the string;
(3) load string constant "Huangweifeng" (str_2);
(4) Call the frame of the string (Constructor);
(5) Save the string in the array (starting at position 0);
(6) get static out variable from Java.io.PrintStream class;
(7) generate a new string buffer variable new StringBuffer (str_buf_1);
(8) Copy the string buffer variable;
(9) invokes the string-buffered frame (Constructor);
( Save the string buffer into the array (starting at position 1);
(one) Append method in string buffer (StringBuffer) class with str_1 as parameter;
(12) Load string constant "Is my name" (str_3);
(StringBuffer) invokes the Append method in the string buffer (Str_3) class as a parameter;
Executes the tostring command for str_buf_1;
(+) calls the Println method in the Out variable, outputting the result. &NBSP
As you can see, these two lines of simple code generate str_1,str_2,str_3,str_4 and str_buf_1 five object variables. Instances of these generated classes are generally stored in the heap. The heap is to initialize the superclass of all classes, the instances of the class, and also to invoke the architect of the class extremely each superclass. These operations consume system resources very much. Therefore, it is absolutely necessary to restrict the generation of objects. &NBSP
has been modified to replace the above code with the following code.
StringBuffer name=New stringbuffer ("Huangweifeng"); System.out.println (Name.append (
The system will do the following:
(1) Generate a new string buffer variable new StringBuffer (str_buf_1);
(2) Copy the string buffer variable;
(3) Load string constant "Huangweifeng" (str_1);
(4) Invoking a string-buffered frame (Constructor);
(5) Save the string buffer into the array (starting at position 1);
(6) The static out variables are obtained from the Java.io.PrintStream class;
(7) Loading str_buf_1;
(8) Load string constant "is my Name" (str_2);
(9) Call the Append method in the string buffer (StringBuffer) instance with str_2 as the parameter;
(10) For str_buf_1 Execution ToString Command (str_3);
(11) Call the Println method in the out variable to output the result.
As you can see, the improved code generates only four object variables: Str_1,str_2,str_3 and str_buf_1. You may think that building an object less will not improve the performance of the program greatly. However, the following code snippet 2 will execute twice times as fast as the code Snippet 1. Because code snippet 1 generates eight objects, Code snippet 2 generates only four objects.
Code Snippet 1:
New StringBuffer ("Huangweifeng"); Name+ = "is my"; Name
Code Snippet 2:
StringBuffer name=New stringbuffer ("Huangweifeng"); Name.append ("is my"); Name.append ("name."). ToString ();
Therefore, it is very important to make full use of the library functions provided by Java to improve the performance of Java programs. The main points of attention are as follows;
(1) Use static variables as much as possible (statically Class Variables)
If a variable in a class does not change with his instance, it can be defined as a static variable, so that all of his instances share the variable.
Cases:
Public class Foo {someobjectso =new
It can be defined as:
Public class static someobject so=New
(2) Do not make too many changes to the objects that have been generated.
For some classes, such as the string class, it would be better to regenerate a new object instance instead of modifying an object instance that has already been generated.
Cases:
String name= "Huang"; name= "Wei"; name
The code above generates three object instances of type string. The first two need a system for garbage collection immediately. If you want to connect to a string, the performance will be worse because the system will not generate more temporary variables for this, as shown in Example 1 above.
(3) When an object is generated, it is allocated to a reasonable amount of space and size in Java, many classes have its default space allocation size. For the StringBuffer class, the default allocation space size is 16 characters. If the size of the space used in the program is not 16 characters, the StringBuffer must be initialized correctly.
(4) Avoid generating objects or variables that are less-used or short-life-cycle. For this scenario, an object buffer pool is defined. It is much less expensive to manage an object buffer pool than to generate and reclaim objects frequently.
(5) Initialize only within the scope of the object. Java allows the definition and initialization of objects anywhere in the code. In this way, you can initialize only within the scope of the object's action. Thus saving the system overhead.
Cases:
Someobject so=New someobject (); if (x==1) then {Foo=if(x==1) and then {someobjectso =new someobject (); Foo=
2. Exception (Exceptions)
The Java language provides try/catch to make it easy for users to catch exceptions and handle exceptions. But if used improperly, it will also affect the performance of the Java program. Therefore, pay attention to the following two points:
(1) Avoid logical use of the application Try/catch
If you can use If,while and other logical statements to deal with, then as far as possible without the Try/catch statement.
(2) Reusing exceptions
When the exception must be handled, the exception object that already exists is reused whenever possible. It takes most of the time to generate an exception object in the handling of the exception.
3. Threads (threading)
Threads are typically used in a high-performance application. Because threads can take full advantage of the system's resources. The program can continue processing and running while other threads are waiting for the hard disk or the network to read and write. However, improper use of threads can also affect the performance of the program.
Example 2: Correct use of the vector class
Vectors are primarily used to hold various types of objects (including objects of the same type and different types). However, in some cases, the use of the program will have a performance impact. This is mainly determined by the two characteristics of the vector class. First, the vector provides a thread-safe protection function. Even though many methods in the vector class are synchronized. But if you have confirmed that your application is single-threaded, the synchronization of these methods is completely unnecessary. Second, when vectors look for various objects stored, it often takes a lot of time to match the types. And when these objects are of the same type, these matches are completely unnecessary. Therefore, it is necessary to design a single-threaded, class or collection that holds a particular type of object in place of the vector class. The program to replace is as follows (Stringvector.java):
Public classStringvector {PrivateString [] data; Private intcount; PublicStringvector () { This(10);//default size is ten} PublicStringvector (intinitialsize) {Data=NewString[initialsize]; } Public voidAdd (String str) {//Ignore null stringsif(str = =NULL) {return; } Ensurecapacity (Count+ 1); Data[count++] =str; } Private voidEnsurecapacity (intmincapacity) { intOldcapacity =data.length; if(Mincapacity >oldcapacity) {String olddata[]=data; intnewcapacity = oldcapacity * 2; Data=NewString[newcapacity]; System.arraycopy (OldData,0, data, 0, Count); } } Public voidRemove (String str) {if(str = =NULL) {return;//ignore null str} for(inti = 0; I < count; i++) { //Check for a matchif(Data[i].equals (str)) {system.arraycopy (data,i+1,DATA,I,COUNT-1);//Copy Data//Allow previously valid array element is Gc′dData[--count] =NULL; return; } } } Public FinalString Getstringat (intindex) { if(Index < 0) {return NULL; } Else if(Index > Count) {return NULL;//index is > # strings}Else{returnData[index];//index is good}} }
Therefore, the code:
Vector strings=new vector (); Strings.add ("one"); Strings.add ("both"); String Second
You can replace it with the following code:
Stringvector strings=New stringvector (); Strings.add ("one"); Strings.add ("both"); String Second
This makes it possible to improve the performance of Java programs by optimizing threads. The program used for testing is as follows (Testcollection.java):
ImportJava.util.Vector; Public classtestcollection { Public Static voidMain (String args []) {testcollection collect=Newtestcollection (); if(Args.length = = 0) {System.out.println ("Usage:java testcollection [Vector | Stringvector] "); System.exit (1); } if(Args[0].equals ("vector") {Vector store=NewVector (); LongStart =System.currenttimemillis (); for(inti = 0; i < 1000000; i++) {store.addelement ("String"); } Longfinish =System.currenttimemillis (); System.out.println ((Finish-start)); Start=System.currenttimemillis (); for(inti = 0; i < 1000000; i++) {String result=(String) store.elementat (i); } Finish=System.currenttimemillis (); System.out.println ((Finish-start)); } Else if(Args[0].equals ("Stringvector") {Stringvector store=NewStringvector (); LongStart =System.currenttimemillis (); for(inti = 0; i < 1000000; i++) {store.add ("string"); } Longfinish =System.currenttimemillis (); System.out.println ((Finish-start)); Start=System.currenttimemillis (); for(inti = 0; i < 1000000; i++) {String result=Store.getstringat (i); } Finish=System.currenttimemillis (); System.out.println ((Finish-start)); } } }
There are several things to keep in mind about threading:
(1) to prevent excessive synchronization
As shown above, unnecessary synchronization often results in a decrease in program performance. Therefore, if the program is single-threaded, you must not use synchronization.
(2) Synchronous method instead of synchronizing entire code snippet
Synchronizing a method or function is better than synchronizing the entire code snippet.
(3) A mechanism to use multiple "locks" on each object to increase concurrency.
In general, there is only one "lock" for each object, which indicates that a "deadlock" occurs if two threads execute two different synchronization methods for an object. Even though the two methods do not share any resources. To avoid this problem, a "multi-lock" mechanism can be applied to an object. As shown below:
classFoo {Private Static intvar1;Private StaticObject lock1=NewObject ();Private Static intvar2;Private StaticObject lock2=NewObject (); Public Static voidincrement1 () {synchronized(lock1) {var1++; } } Public Static voidIncrement2 () {synchronized(lock2) {var2++; } } }
4. Input and output (I/O)
Inputs and outputs include many aspects, but most involve read and write operations to the hard disk, network, or database. There are caches and no caches for read and write operations, and there are several types of JDBC drives that can be selected for database operations. However, it will affect the performance of the program. Therefore, there are several points to note:
(1) using input/output buffering
Use the cache as much as possible. However, if you want to flush the cache frequently, we recommend that you do not use the cache.
(2) Output stream and Unicode string
When using the output stream and the Unicode string, the Write class had a higher overhead. Because it wants to implement a Unicode-to-byte (byte) conversion. Therefore, if possible, the conversion is implemented before the write class is used or the OutputStream class is used instead of the writer class.
(3) Use transient when serialization is required
When serializing a class or an object, the transient type is known for those atomic types (atomic) or primitives that can be rebuilt. This does not have to be serialized every time. If these serialized objects are to be transmitted over the network, this small change will greatly improve performance.
(4) using caching (cache)
For objects or data that are often used without much change, you can store it in cache. This will increase the speed of access. This is especially important for result sets that are returned from the database.
(5) Using a fast JDBC driver (Driver)
Java provides four ways to access a database. Two of these are JDBC drives. One is a local drive that is outsourced with Java, and the other is a full Java drive. Which one to use depends on the environment of the Java deployment and the application itself.
5. A number of other experiences and techniques
(1) Use local variables.
(2) Avoid calling a function or method (get or set) in the same class to set or invoke a variable.
(3) Avoid generating the same variable in the loop or calling the same function (the parameter variable is the same).
(4) Use static,final,private and other keywords as much as possible.
(5) When copying large amounts of data, use the system.arraycopy () command.
The the-to-optimize Java program design and coding to improve Java performance