Javaコードのパフォーマンス仕上げのアップグレード

1.同時

新しいネイティブスレッドを作成できません......

質問1:どのくらいのメモリ消費量Javaでスレッドを作成するには?

各スレッドは、独自のスタックメモリ、共有メモリヒープを持っています

質問2:どのくらいのマシンスレッドの作成ができますか?

CPU、メモリ、オペレーティングシステム、JVM、アプリケーション・サーバ

私たちは下と非スレッドプールのスレッドプールの違いを確認するために、サンプルコードを記述します。

//线程池和非线程池的区别
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();
     }
 }

スレッドの異なる数を起動し、結果と非スレッドプールのスレッドプールを比較します。

非スレッド・プール スレッドプール
100回 16ミリ 5msの
1000年 90ミリ 28ms
10000 1329ms 164ms

結論:新しいスレッドを(DO)、スレッドプール

非スレッドプールの短所:

  • あなたは、パフォーマンスの消費を作成するたびに
  • 障害管理の欠如。簡単に無制限のスレッド、OOMと原因のクラッシュを作成します

問題に注意を払うために1.1スレッドプール

デッドロックを避けるため、CASを使用するようにしてください

私たちは楽観的ロックの実装例を記述します。

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);
     }
 }

注意を払うことにThreadLocalを使用して、

それを参照する外部ThreadLocalの強い参照が存在しない場合、キーとして弱参照をThreadLocalの使用、ThreadLocalのを回収するためにバインドし、システムGC、ThreadLocalMapにNULLエントリの鍵となるように、いいえがあるだろうThreadLocalMap現在のスレッドがまだ終了を遅らせる場合はnull値にアクセスするには、これらの重要な方法への参入は、null値を入力するためのこれらのキーは常に参照の強いチェーンを存在します:参考スレッド - >スレッド - > ThreaLocalMap - >エントリ - >値は、メモリリークが生じる、回収することはできません。

我々は、適切な使用のThreadLocalMap例を記述します。

//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スレッド間の相互作用

古典的なHashMapのは、無限ループの問題のCPU100%を引き起こします

私たちは、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");
     }
 }

HashMapの無限ループが発生した後、我々はスレッドスタック上の次の情報を観察することができます。

//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)

アプリケーション停滞デッドロック、Spring3.1デッドロックの問題

私たちは、デッドロックの例をシミュレートします:

//死锁的示例
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();
     }
 }

デッドロックが発生した後、我々はスレッドスタック上の次の情報を観察することができます。

//死锁时产生堆栈
"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.

模範的なJUCに基づいて、1.3の最適化

最適化されたカウンタ、我々はパフォーマンスの違いを感謝カウンタを実装するための3つの異なる方法は同期、ReentrantLockの、原子と一緒にいました

//示例代码
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);
     }
 }

結論、高い同時実行、複数のサイクル、高効率化を同期リエントラントロックが、最終的にアトミック最高のパフォーマンス。

2.通信

2.1効率的なデータベース接続プールの問題

  • 最終的には、接続を閉じてください
  • ついにリリースに接続してください

OIO 2.2 /格納された/ AIO

OIO NIO AIO
タイプ おもり ノンブロッキング ノンブロッキング
難易度の使用 シンプル コンプレックス コンプレックス
確実 違い 高いです 高いです
スループット 低いです 高いです 高いです

結論:可能な限り厳格な要件の下でのパフォーマンスは、通信にNIOの方法を使用する必要があります。

2.3 TIME_WAIT(クライアント)、CLOSE_WAIT(サーバー)问题

反応:再発要求が失敗しました

接続を取得します。 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

  • TIME_WAIT:アクティブに近いの最適化システムのカーネル・パラメータを示します。
  • CLOSE_WAIT:パッシブクローズを表します。
  • 設立:コミュニケーションは、それがあると述べました

解決策:シャットダウンを余儀なくされ、2段目の終了後

2.4シリアル接続、固定接続(長いリンク)、パイプの接続

図1

結論:

最も優れた性能の配管接続の永続性をシリアル接続に基づいて、接続時間を閉じる/開くことによって減少されます。

パイプによる接続制限:

1、HTTPクライアントは、(非ターミナルを使用してサーバーに通常サーバー)の永続を確認することができません。

図2は、応答情報は、注文依頼情報の順序と一致しなければなりません。

図3は、それを使用することができる接続管の冪等の操作をサポートしなければなりません。

3.データベースの操作

インデックス(時間クエリによって特別な注意を)持っている必要があります

単一の操作またはバッチ操作

注意:多くのプログラマランダムに単一の操作を使用するときにコードを書くが、性能要件の前提の下で、操作のバッチモードを使用する必要があります。

4.JVM

ステップ4.1 CPU上昇の通常のプロセス

  • top高いCPUを消費するプロセスを見つけます
  • top –H –pどのスレッド高いCPU消費をご覧ください
  • CPUの消費量は、スレッドの最大数を記録しました
  • printf %x変換PIDのためのベースとなります
  • jstackスタック情報記録処理
  • CPUスレッド情報の最も高い消費を探します

4.2メモリ標高(OOM)一般的なプロセス工程

  • jstatビューFGCコマンドが発生し、時間が消費、より多くの数、長い時間のかかる問題を示しています。
  • 連続ビューjmap –heap占有の表示古い世代は、プログラムに大きな変更は、問題を示しています。
  • 連続使用してjmap –histo:live、ファイルをエクスポート差よりも、オブジェクトをロードするためのコマンドを、違いは問題がある部分が通常です。

単球の4.3 GC-誘発標高

シングルCPU占​​有率、GCからの最初のチェック。

SYの4.4共通の標高

  • スレッドのコンテキストは、頻繁に切り替え
  • あまりにも多くのスレッド
  • ロック競争

4.5 iowaitの標高

CPU使用率が高いIOである場合、調査は、NIOに変換OIOとして、IOプログラムに関する。

4.6ジッタの問題

理由:マシンコードに必要なCPUのタイムスライスにバイトコード、バイトコードの実装におけるCPUの多くは、長い間高いままにするCPUの原因となります。

現象:「C2 CompilerThread1」デーモンは、「C2 CompilerThread0」デーモンのCPU占有率が最も高いです。

ソリューション:CPUの割合がスレッドをコンパイルすることを確実にします。

おすすめ

転載: www.cnblogs.com/timspace/p/11015286.html