Java improvement class (I) thread explanation
1、 Overview
Before learning thread, let's first understand the relationship between threads and processes:
From the above description, we can know that thread is the basic scheduling unit of CPU. Only by making good use of multithreading can we make full use of the multi-core resources of CPU.
This article is based on JDK 8 (also known as JDK 1.8).
2、 Thread usage
2.1 start thread
There are four ways to create threads:
2.1. 1. Creation method of runnable
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
Thread thread = new Thread(new MyThread());
thread.start();
2.1. 2. Inherit thread creation method
public class MyThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
MyThread thread = new MyThread();
thread.start();
The above code can be written in a simpler way, as follows:
Thread thread = new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
thread.start();
2.1. 3 lambda creation method
new Thread(()-> System.out.println(Thread.currentThread().getName())).start();
2.1. 4 using callable and future
From the source code, we can know that the parent class of thread is runnable and jdk1 0, and callable is similar to runnable, which is jdk1 5 makes up for the situation that the calling thread does not return a value. It can be regarded as a supplement to runnable. Let's take a look at the implementation of callable.
public class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName());
return Thread.currentThread().getName();
}
}
Callable<String> callable = new MyThread();
FutureTask<String> ft = new FutureTask<>(callable);
new Thread(ft,"threadName").start();
System.out.println(ft.get());
2.1. 5. The difference between run() and start()
It is the start () method that really starts the thread, not run (). Like ordinary member methods, run () can be reused, but it cannot start a new thread.
2.2 common methods of thread
Thread class method
Thread static method
2.3 difference between sleep() and wait()
Sleep is a thread method and wait is an object method. Their functions are similar. The most essential difference is that sleep does not release the lock and wait releases the lock.
Different usage: sleep (milliseconds) can wake him up automatically by specifying the time. If the time is less than, you can only call interreput () to terminate the thread; Wait() can be called directly with notify() / notifyall().
Key points: the code for testing the lock release of wait and sleep is as follows:
public class SynchronizedTest extends Thread {
int number = 10;
public synchronized void first(){
System.out.println("this is first!");
number = number+1;
}
public synchronized void secord() throws InterruptedException {
System.out.println("this is secord!!");
Thread.sleep(1000);
// this.wait(1000);
number = number*100;
}
@Override
public void run() {
first();
}
}
SynchronizedTest synchronizedTest = new Synchronizedtest();
synchronizedTest.start();
synchronizedTest.secord();
// 主线程稍等10毫秒
Thread.sleep(10);
System.out.println(synchronizedTest.number);
According to the results:
Summary: using sleep (1000) does not release the synchronization lock, execute 10 * 100 + 1 = 1001, wait (1000) releases the lock, and the execution order is (10 + 1) X100 = 1100, so sleep does not release the lock, wait releases the lock.
3、 Thread state
3.1 thread status overview
Thread status:
The status of the thread can be viewed using getstate(). For more status details, see the thread source code, as shown in the following figure:
3.2 implementation of thread status code
3.2. 1 new has not been started
Thread thread = new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
// 只声明不调用start()方法,得到的状态是NEW
System.out.println(thread.getState()); // NEW
3.2. 2 runnable running status
Thread thread = new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
thread.start();
System.out.println(thread.getState()); // RUNNABLE
3.2. 3 blocked
The synchronized synchronization blocking is implemented. The code is as follows:
public class MyCounter {
int counter;
public synchronized void increase() {
counter++;
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
MyCounter myCounter = new MyCounter();
// 线程1调用同步线程,模拟阻塞
new Thread(()-> myCounter.increase()).start();
// 线程2继续调用同步阻塞方法
Thread thread = new Thread(()-> myCounter.increase());
thread.start();
// 让主线程等10毫秒
Thread.currentThread().sleep(10);
// 打印线程2,为阻塞状态:BLOCKED
System.out.println(thread.getState());
3.2. 4 waiting permanent waiting state
public class MyThread extends Thread{
@Override
public void run() {
synchronized (MyThread.class){
try {
MyThread.class.wait();
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread thread = new Thread(new MyThread());
thread.start();
// 主线程挂起200毫秒,等thread执行完成
Thread.sleep(200);
// 输出WAITING,线程thread一直处于被挂起状态
System.out.println(thread.getState());
Wake up thread: the notify / notifyAll method can be used. The code is as follows:
synchronized (MyThread.class) {
MyThread.class.notify();
}
Method to make thread waiting:
You can know the join method of thread by viewing the thread source code. The bottom layer uses the wait implementation of object, as shown in the following figure:
Note: looking at the source code of the object, we can see that wait() does not pass parameters, which is equivalent to wait (0). The set "0" is not executed immediately, but waits indefinitely, not executed, as shown in the following figure:
3.2. 5 TIMED_ Waiting timeout wait state
TIMED_ In the waiting status, you only need to set the time for the wait. The code is as follows:
public class MyThread extends Thread{
@Override
public void run() {
synchronized (MyThread.class){
try {
MyThread.class.wait(1000);
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The calling code is the same as follows:
Thread thread = new Thread(new MyThread());
thread.start();
// 主线程挂起200毫秒,等thread执行完成
Thread.sleep(200);
// 输出TIMED_WAITING
System.out.println(thread.getState());
synchronized (MyThread.class) {
MyThread.class.notify();
}
3.2. 6 terminated status
Thread thread = new Thread(()-> System.out.println(Thread.currentThread().getName()));
thread.start();
// 让主线程等10毫秒
Thread.currentThread().sleep(10);
System.out.println(thread.getState());
4、 Deadlock
According to the previous knowledge, we know that the lock is not released when using sleep, so we can easily write deadlock code by using this feature. The specific process is shown in the figure (the picture comes from teacher Yang Xiaofeng's article):
The code is as follows:
static Object object1 = new Object();
static Object object2 = new Object();
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
synchronized (object1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object2){
System.out.println(Thread.currentThread().getName());
}
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
synchronized (object2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object1){
System.out.println(Thread.currentThread().getName());
}
}
}
};
thread.start();
thread2.start();
Run the above code and the program will be waiting indefinitely.
5、 Summary
According to the above content, we have systematically learned the use of thread, but learning without thinking is useless. Finally, let's leave a question: according to the knowledge introduced in this article, how can deadlock be avoided? (ha ha, sell a pass. You can get the answer according to the combination of knowledge points in the article)
Source code download: https://github.com/vipstone/java-core-example.git
Recommendation part
I recently read the course of Yang Xiaofeng, former chief engineer of Oracle, who is also the owner of the flow chart cited in the fourth part. I feel very good. I recommend it to you. Let's learn the Java core systematically.
Reference documents
https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html