Java code performance finishing upgrade

1. Concurrent

Unable to create new native thread ……

Question 1: How much memory consumption to create a thread in Java?

Each thread has its own stack memory, shared memory heap

Question 2: How much can a machine thread creation?

CPU, memory, operating system, JVM, application server

We write a sample code to verify the difference between the lower and non-thread pool thread pool:

//线程池和非线程池的区别
public class ThreadPool {
 
     public static int times = 100; // 100,1000,10000
 
     public static ArrayBlockingQueue arrayWorkQueue = new ArrayBlockingQueue(1000);
     public static ExecutorService threadPool = new ThreadPoolExecutor(5,// corePoolSize线程池中心核心线程数
             10,
             60,
             TimeUnit.SECONDS,
             arrayWorkQueue,
             new ThreadPoolExecutor.DiscardOldestPolicy()
     );
 
     public static void useThreadPool(){
         Long start = System.currentTimeMillis();
         for(int i = 0; i <times; i ++){
             threadPool.execute(new Runnable(){
                 public void run(){
                     System.out.println("说点什么吧......"),
                 }
             });
         }
         threadPool.shutdown();
         while(true){
             if(threadPool.isTerminated()){
                 Long end = System.currentTimeMillis();
                 System.out.println(end  -  start);
                 break;
             }
         }
     }
 
     public static void createNewThread(){
         Long start = System.currentTimeMillis();
         for(int i = 0; i < times; i ++){
 
             new Runnable() {
                 public void run(){
                     System.out.println( "说点什么吧......");
                 }
             }.start();
         }
         Long end = System.currentTimeMillis();
         System.out.println(end  -  start);
     }
 
     public static void main(String args []){
         createNewThread();
         // useThreadPool();
     }
 }

Start a different number of threads, and then compare the results and non-thread pool thread pool:

Non-thread pool Thread Pool
100 times 16 ms The 5ms
1000 90 ms 28ms
10000 1329ms 164ms

Conclusion: Do new Thread (), thread pool

Non-thread pool Cons:

  • Each time you create Performance consumption
  • Disorder, lack of management. Easily create unlimited threads, OOM and cause crashes

1.1 thread pool to pay attention to the problem

Avoid deadlock, try to use CAS

We write an optimistic locking implementation example:

public CASLock {
 
     public static int money = 2000;
 
     public static boolean add2(int oldm,int newm){
         try{
             Thread.sleep(2000);
         } catch(InterruptedException e){
             e.printStackTrace();
         }
         if(money == oldm){
             money = money + newm;
             return true;
         }
         return false;
     }
 
     public synchronized static void add1(int newm){
         try{
             Thread.sleep(3000);
         } catch(InterruptedException e){
             e.printStackTrace();
         }
         money = money + newm;
     }
 
     public static void add(int newm){
         try{
             了Thread.sleep(3000);
         } catch(InterruptedException e){
             e.printStackTrace();
         }
         money = money + newm;
     }
 
     public static void main(String args[]) {
         Thread one = new Thread() {
             public void run() {
                 //add(5000)
                 while (true) {
                     if (add2(money, 5000)) {
                         break;
                     }
                 }
             }
         };
         Thread two = new Thread() {
             public void run() {
                 //add(7000)
                 while (true) {
                     if (add2(money, 7000)) {
                         break;
                     }
                 }
             }
         };
         one.start();
         two.start();
         try {
             one.join();
             two.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println(money);
     }
 }

Use ThreadLocal to pay attention

ThreadLocalMap use ThreadLocal weak reference as a key, if there is no external ThreadLocal a strong references to refer to it, then the system GC when the ThreadLocal bound to be recovered, so that, in ThreadLocalMap will be key to null Entry, there will be no Entry into these key way to access the value null if the current thread still delay the end, these key for the Entry of the value null will always exist a strong chain of references: thread Ref -> thread -> ThreaLocalMap -> Entry - > value can never be recovered, resulting in a memory leak.

We write a ThreadLocalMap example of the proper use of:

//ThreadLocal应用实例
public class ThreadLocalApp {
 
     public static final ThreadLocal threadLocal = new ThreadLocal();
 
     public static void muti2() {
         int i[] = (int[]) threadLocal.get();
         i[1] = i[0] * 2;
         threadLocal.set(i);
     }
 
     public static void muti3() {
         int i[] = (int[]) threadLocal.get();
         i[2] = i[1] * 3;
         threadLocal.set(i);
     }
 
     public static void muti5() {
         int i[] = (int[]) threadLocal.get();
         i[3] = i[2] * 5;
         threadLocal.set(i);
     }
 
     public static void main(String args[]) {
         for (int i = 0; i < 5; i++) {
             new Thread() {
                 public void run() {
                     int start = new Random().nextInt(10);
                     int end[] = {0, 0, 0, 0};
                     end[0] = start;
                     threadLocal.set(end);
                     ThreadLocalApp.muti2();
                     ThreadLocalApp.muti3();
                     ThreadLocalApp.muti5();
                     //int end = (int) threadLocal.get();
                     System.out.println(end[0] + "  " + end[1] + "  " + end[2] + "  " + end[3]);
                     threadLocal.remove();
                 }
             }.start();
         }
     }
 }

1.2 thread interactions - problems caused by thread-unsafe

The classic HashMap cause an infinite loop problem CPU100%

We simulate an example of an infinite loop of HashMap:

//HashMap死循环示例
public class HashMapDeadLoop {
 
     private HashMap hash = new HashMap();
 
     public HashMapDeadLoop() {
         Thread t1 = new Thread() {
             public void run() {
                 for (int i = 0; i < 100000; i++) {
                     hash.put(new Integer(i), i);
                 }
                 System.out.println("t1 over");
             }
         };
 
         Thread t2 = new Thread() {
             public void run() {
                 for (int i = 0; i < 100000; i++) {
                     hash.put(new Integer(i), i);
                 }
                 System.out.println("t2 over");
             }
         };
         t1.start();
         t2.start();
     }
 
     public static void main(String[] args) {
         for (int i = 0; i < 1000; i++) {
             new HashMapDeadLoop();
         }
         System.out.println("end");
     }
 }

After HashMap infinite loop occurs, we can observe the following information on the thread stack:

//HashMap死循环产生的线程栈
Thread-281" #291 prio=5 os_prio=31 tid=0x00007f9f5f8de000 nid=0x5a37 runnable [0x0000700006349000]
   java.lang.Thread.State: RUNNABLE
       at java.util.HashMap$TreeNode.split(HashMap.java:2134)
       at java.util.HashMap.resize(HashMap.java:713)
       at java.util.HashMap.putVal(HashMap.java:662)
       at java.util.HashMap.put(HashMap.java:611)
       at com.example.demo.HashMapDeadLoop$2.run(HashMapDeadLoop.java:26)

Application stagnant deadlock, Spring3.1 the deadlock problem

We simulate an example of a deadlock:

//死锁的示例
public class DeadLock {
     public static Integer i1 = 2000;
     public static Integer i2 = 3000;
         public static synchronized Integer getI2() {
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         return i2;
     }
     public static void main(String args[]) {
         Thread one = new Thread() {
             public void run() {
                 synchronized (i1) {
                     try {
                         Thread.sleep(3000);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     synchronized (i2) {
                         System.out.println(i1 + i2);
                     }
                 }
             }
         };
         one.start();
         Thread two = new Thread() {
             public void run() {
                 synchronized (i2) {
                     try {
                         Thread.sleep(3000);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     synchronized (i1) {
                         System.out.println(i1 + i2);
                     }
                 }
             }
         };
         two.start();
     }
 }

After a deadlock occurs, we can observe the following information on the thread stack:

//死锁时产生堆栈
"Thread-1":
       at com.example.demo.DeadLock$2.run(DeadLock.java:47)
       - waiting to lock  (a java.lang.Integer)
       - locked  (a java.lang.Integer)
"Thread-0":
       at com.example.demo.DeadLock$1.run(DeadLock.java:31)
       - waiting to lock  (a java.lang.Integer)
       - locked  (a java.lang.Integer)
Found 1 deadlock.

1.3 Optimization Based on the exemplary JUC

An optimized counter, we were with Synchronized, ReentrantLock, Atomic three different ways to implement a counter, which appreciate the difference in performance

//示例代码
public class SynchronizedTest {
 
     public static int threadNum = 100;
     public static int loopTimes = 10000000;
 
     public static void userSyn() {
         //线程数
         Syn syn = new Syn();
         Thread[] threads = new Thread[threadNum];
         //记录运行时间
         long l = System.currentTimeMillis();
         for (int i = 0; i < threadNum; i++) {
             threads[i] = new Thread(new Runnable() {
                 @Override
                 public void run() {
                     for (int j = 0; j < loopTimes; j++) {
                         //syn.increaseLock();
                         syn.increase();
                     }
                 }
             });
             threads[i].start();
         }
         //等待所有线程结束
         try {
             for (int i = 0; i < threadNum; i++)
                 threads[i].join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println("userSyn" + "-" + syn + " : " + (System.currentTimeMillis() - l) + "ms");
     }
 
     public static void useRea() {
         //线程数
         Syn syn = new Syn();
         Thread[] threads = new Thread[threadNum];
         //记录运行时间
         long l = System.currentTimeMillis();
         for (int i = 0; i < threadNum; i++) {
             threads[i] = new Thread(new Runnable() {
                 @Override
                 public void run() {
                     for (int j = 0; j < loopTimes; j++) {
                         syn.increaseLock();
                         //syn.increase();
                     }
                 }
             });
             threads[i].start();
         }
         //等待所有线程结束
         try {
             for (int i = 0; i < threadNum; i++)
                 threads[i].join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println("userRea" + "-" + syn + " : " + (System.currentTimeMillis() - l) + "ms");
     }
    public static void useAto() {
         //线程数
         Thread[] threads = new Thread[threadNum];
         //记录运行时间
         long l = System.currentTimeMillis();
         for (int i = 0; i < threadNum; i++) {
             threads[i] = new Thread(new Runnable() {
                 @Override
                 public void run() {
                     for (int j = 0; j < loopTimes; j++) {
                         Syn.ai.incrementAndGet();
                     }
                 }
             });
             threads[i].start();
         }
         //等待所有线程结束
         try {
             for (int i = 0; i < threadNum; i++)
                 threads[i].join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println("userAto" + "-" + Syn.ai + " : " + (System.currentTimeMillis() - l) + "ms");
     }
 
     public static void main(String[] args) {
         SynchronizedTest.userSyn();
         SynchronizedTest.useRea();
         SynchronizedTest.useAto();
     }
 }
 
 class Syn {
     private int count = 0;
     public final static AtomicInteger ai = new AtomicInteger(0);
 
     private Lock lock = new ReentrantLock();
 
     public synchronized void increase() {
         count++;
     }
 
     public void increaseLock() {
         lock.lock();
         count++;
         lock.unlock();
     }
 
     @Override
     public String toString() {
         return String.valueOf(count);
     }
 }

Conclusion, high concurrency, multiple cycles, the reentrant lock Synchronized higher efficiency, but eventually Atomic best performance.

2. Communication

2.1 Efficient database connection pool problem

  • Be sure to close the connection finally
  • Be sure to connect in the finally release

OIO 2.2 / stored / AIO

OIO NIO AIO
Types of Clog Non-blocking Non-blocking
Use of difficulty simple complex complex
reliability difference high high
Throughput low high high

Conclusion: The performance under stringent requirements, as far as possible should be used NIO way to communicate.

2.3 TIME_WAIT(client),CLOSE_WAIT(server)问题

Reaction: Recurrent request failed

Gets connection netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

  • TIME_WAIT: indicates active close optimize system kernel parameters.
  • CLOSE_WAIT: represents the passive close.
  • ESTABLISHED: Communication said it is

Solution: After the completion of the second stage forced to shut down

2.4 serial connection, a persistent connection (long link), the connection of the pipe

figure 1

in conclusion:

The most outstanding performance pipe connection persistence is reduced by opening / closing the connection time on the basis of the serial connection.

Piped connection limits:

1, HTTP client can not be confirmed persistent (usually the server to the server using a non-terminal);

2, the response information must be consistent with the order of the order request information;

3, it must support idempotent operations of connecting pipes may be used.

3. Database Operations

Must have an index (special attention by the time the query)

A single operation or batch operation

Note: Many programmers writing code when using a random way a single operation, but under the premise of performance requirements, require the use of a batch mode of operation.

4.JVM

Usually the process of step 4.1 CPU elevation

  • topFind out which process consumes high cpu
  • top –H –pFind out which thread high cpu consumption
  • Cpu consumption recorded the highest number of threads
  • printf %xBe the base for the conversion pid
  • jstackStack information recording process
  • Find the highest consumption of cpu thread information

4.2 Memory elevation (the OOM) General process steps

  • jstatViews FGC command occurs and the time consumed, the more the number, the longer the time-consuming indicate a problem;
  • Continuous View jmap –heapView Older Generation of occupancy, the greater the change in the program indicate a problem;
  • Using a continuous jmap –histo:livecommand to export a file, load an object than the difference, the difference is usually part where the problem is.

4.3 GC-induced elevation of monocytes

Single CPU occupancy rate, first check from the GC.

4.4 Common elevation of SY

  • Thread context switching frequently
  • Too many threads
  • Lock competition

4.5 Iowait elevation

If the CPU usage is high IO, the investigation relates to the IO program, such as the OIO transformed into NIO.

4.6 jitter problems

The reason: the bytecode into machine code required CPU time slice, a lot of CPU in the implementation of the byte code, causes the CPU to remain high for long;

Phenomenon: "C2 CompilerThread1" daemon, "C2 CompilerThread0" daemon CPU occupancy rate is highest;

Solution: to ensure that the proportion of CPU to compile threads.

Guess you like

Origin www.cnblogs.com/timspace/p/11015286.html