table of Contents
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
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
top
Find out which process consumes high cputop –H –p
Find out which thread high cpu consumption- Cpu consumption recorded the highest number of threads
printf %x
Be the base for the conversion pidjstack
Stack information recording process- Find the highest consumption of cpu thread information
4.2 Memory elevation (the OOM) General process steps
jstat
Views FGC command occurs and the time consumed, the more the number, the longer the time-consuming indicate a problem;- Continuous View
jmap –heap
View Older Generation of occupancy, the greater the change in the program indicate a problem; - Using a continuous
jmap –histo:live
command 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.