Java multithreading and java Multithreading
Processes and threads
Before learning Java multithreading, let's briefly review the process and thread knowledge.
Process: A process is the basic unit for the system to allocate and schedule resources. It can be understood as a running program, such as a game.
Thread: A thread is the smallest unit of program execution. A process can be composed of one or more threads. In a running game, the interface is usually displayed.
The thread overhead of thread switching is much smaller than that of process switching.
Figure 1
In Figure 1, the blue box indicates the process, and the yellow box indicates the thread. Processes have code, data, and other resources. These resources are shared and can be used by three threads.
And each thread has a private stack space.
Java thread status chart
Five States of a thread:
1) New State (New): After the thread object is instantiated, it enters the New state.
2) ready state (Runnable): After the thread object is instantiated, other threads call the start () method of the object, and the virtual machine starts
The thread is in the ready state and may be scheduled to run at any time.
3) Running status (Running): The thread obtains the time slice and starts execution. You can only enter the running status from the ready status.
4) blocking status (Blocked): The thread suspends execution for some reason and gives the CPU right to use it.
Waiting for blocking: Call the wait () method of the running thread to put the thread into the waiting pool.
Synchronization congestion: When the running thread obtains the synchronization lock of the object, the lock has been obtained by other threads, and the virtual opportunity puts the thread into the lock pool.
Other threads: Call the sleep () method or join () method of the running thread, or enter the blocking state when the thread sends an I/O Request.
5) end state (Dead): When the thread completes normal execution or exits abnormally, it enters the end state.
Java thread implementation
The Java language provides two ways to implement threads:
1) Implement threads by inheriting the Thread class
Public class ThreadTest {public static void main (String [] args) {Thread thread = new MyThread (); // create thread Thread. start (); // start thread }}
// Inherit the Thread class MyThread extends Thread {@ Override public void run () {int count = 7; while (count> 0) {System. out. println (count); try {Thread. sleep (1000);} catch (InterruptedException e) {e. printStackTrace ();} count --;}}}
2) Implement the thread through the Runnable interface
Public class ThreadTest {public static void main (String [] args) {Runnable runnable = new MyThread ();
// Pass the Runnable object to the Thread constructor Thread thread = new Thread (runnable); thread. start ();}}
// Implemented the Runnable interface class MyThread implements Runnable {@ Override public void run () {int count = 7; while (count> 0) {System. out. println (count); try {Thread. sleep (1000);} catch (InterruptedException e) {e. printStackTrace ();} count --;}}}
Both methods overwrite the run () method. The run () method defines the thread execution content. We can only use the start () method of the thread.
Start the thread, and the start () method can only be called once. When the thread enters the execution status, the virtual Opportunity calls back the thread's run () method. Straight
The run () method of the call thread does not start the thread, but is executed just like a normal method.
In fact, the Thread class also implements the Runnable interface. Both methods can implement threads, but Java only supports single-step
If the Thread class is extended, other classes cannot be extended, far from implementing interface flexibility.
Common thread Methods
1) Thread class
Thread (): used to construct a new Thread.
Thread (Runnable target): used to construct a new Thread, which uses the run method of the specified target.
Thread (ThreadGroup group, Runnable target): used to construct a new Thread in the specified Thread group.
The thread uses the run method of the specified target.
CurrentThread (): Get the object reference of the current running thread.
Interrupt (): sets the current thread to the interrupted state.
Sleep (long millis): enables the current running thread to sleep. The sleep time must be at least a specified number of milliseconds.
Join (): Wait for the end of this thread, that is, calling other. join () in a thread will continue the thread after the end of the other thread.
Yield (): The currently executed thread gives you the right to use the CPU. It enters the ready state from the running state and allows other ready threads to execute.
2) Object class
Wait (): enables the current thread to wait for blocking until other threads call the notify () or yyall () method of this object, when
The former thread is awakened and enters the ready state.
Y (): Wake up a single thread waiting on this object monitor.
Yyall (): Wake up the thread that is waiting on this object monitor.
Note: wait (), Y (), and notifyAll () depend on synchronization locks. The synchronization locks are held by objects and each object has only one.
These methods are defined in the Object class instead of the Thread class.
3) Comparison of yield (), sleep (), and wait ()
Wait (): enables a thread to wait for blocking from the running status, and releases the synchronization lock it holds.
Yield (): enables the thread to enter the ready state from the running state, and does not release the synchronization lock held by the lock.
Sleep (): enables the thread to enter the blocking state from the running state, and does not release the synchronization lock held by the lock.
Thread Synchronization
Let's take a look at a multi-threaded simulated ticket selling example. There are 7 tickets in total, and two threads sell tickets at the same time:
Public class ThreadTest {public static void main (String [] args) {Runnable r = new MyThread (); Thread t1 = new Thread (r ); thread t2 = new Thread (r); t1.start (); t2.start () ;}} class MyThread implements Runnable {private int tickets = 7; // Number of votes @ Override public void run () {while (tickets> 0) {System. out. println ("tickets:" + tickets); tickets --; try {Thread. sleep (100);} catch (InterruptedException e) {e. printStackTrace ();}}}}
Running result:
The running result does not meet our expectation, because the two threads use the shared variable tickets, there is a possibility of data destruction due to cross operations,
This potential interference is called a critical section. Access to the critical section through synchronization can avoid this interference.
In Java, each object has a synchronization lock associated with it, and can be acquired or released by using the synchronized method or statement.
This lock. In multi-threaded collaboration, if access to shared objects is involved, the thread must obtain the synchronization of the object before accessing the object.
Lock. After obtaining the synchronization lock, other threads can be prevented from obtaining the lock until the lock is released by the thread holding the lock.
Public class ThreadTest {public static void main (String [] args) {Runnable r = new MyThread (); Thread t1 = new Thread (r ); thread t2 = new Thread (r); t1.start (); t2.start () ;}} class MyThread implements Runnable {private int tickets = 7; @ Override public void run () {while (tickets> 0) {synchronized (this) {// obtain the synchronization lock of the current object if (tickets> 0) {System. out. println ("tickets:" + tickets); tickets --; try {Thread. sleep (100);} catch (InterruptedException e) {e. printStackTrace ();}}}}}}
Running result:
Synchronized usage:
1) synchronized Method: If a thread needs to call the synchronized Method on an object, it must first obtain
Lock, then execute the method body, and finally release the lock on this object. At the same time, other methods that call the synchronized Method on the same object
The thread will be blocked until the Lock of this object is released.
public synchronized void show(){ System.out.println("hello world");}
2) synchronized static method: the static method can also be declared as synchronized. Each Class has a Class object associated with it,
The static synchronization method obtains the lock on the Class Object of the Class to which it belongs. The two threads cannot execute the static synchronization method of the same Class at the same time, as shown in
If static data is shared among threads, the access to it must be protected by static synchronization.
3) synchronized statement: static statements allow us to obtain the lock on any object, not just the lock on the current object, but also let us determine
The synchronization code area is smaller than the method, so that the thread can hold the lock for as short as possible, thus improving performance.
private final Object lock = new Object();public void show(){ synchronized(lock){ System.out.println("hello world"); }}