ディレクトリ
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、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の割合がスレッドをコンパイルすることを確実にします。