1. Java thread creation mode
In Java, there are three ways to create threads:
- Inherit the Thread class and override the run() method
- Implement the Runnable interface and implement the run() method
- Implement the Callable interface and implement the Call () method
Let’s focus on the first two methods.
1. Create threads by inheriting the Thread class
Inheriting Thread classes must override the run() method to define the Thread body in the run() method, which is the entry point for the new Thread. The thread can only be started by calling the start() method; calling the run() method does not start the thread.
Example 1:
Public class ThreadDemo01 extends Thread{public void run() {for(int I =1; i<=20; I++){system.out.println ("... ); }} public static void main(String[] args) {ThreadDemo01 th=new ThreadDemo01(); // Start thread th.start(); //th.run(); For (int I =1; i<=20; I++){system.out.println ("... ); }}}Copy the code
After executing th.start(), this thread is started, and the statements in this thread are the ones written in the run() method.
Starting a new thread is like having two cars running in two lanes without affecting each other.
If this code is not written in a thread, the code in the run() method is placed next to the for loop in the main method, as if two people were walking down a narrow lane with only one person following the other.
By writing this way we can eat and speak again
2. Create threads by implementing the Runnable interface
By implementing the Runnable interface to create threads, the limitations of single inheritance can be avoided and resources can be shared.
Example 2:
@override public void run() {for(int I =1; @override public void run() {for(int I =1; i<=100; I++){system.out.println (" while running... ); } } public static void main(String[] args) { ThreadDemo02 th=new ThreadDemo02(); Thread t=new Thread(th); T.start (); t.start(); for(int i=1; i<=100; I++){system.out.println ("... ); }}}Copy the code
Since there is no way to start a Thread in the Runnable interface, you need to use the Thread class as a proxy class that calls the start() method to start the Thread.
3. Buy train tickets through multi-thread simulation
Example 3:
Public class implements Runnable{// ticket implements Runnable =20; @override public void run() {// loop while(true){if(kets<=0){break; } try { Thread.sleep(200); // Thread sleep 100ms} catch (InterruptedException e) {e.printstackTrace (); } system.out.println (thread.currentThread ().getname ()+" buy "+tikets--+" buy "); } } public static void main(String[] args) { BuyTikets bt=new BuyTikets(); New Thread(bt," zhang SAN ").start(); New Thread(bt," lI si ").start(); New Thread(bt," w5 ").start(); }}Copy the code
The running result of the program is:
Jack is buying the 20th ticket, Jack is buying the 19th ticket, Jack is buying the 18th ticket, Jack is buying the 16th ticket, Jack is buying the 15th ticket, Jack is buying the 13th ticket, Jack is buying the 12th ticket Tom is buying the 11th ticket Tom is buying the 10th ticket Tom is buying the 9th ticket Tom is buying the 8th ticket Tom is buying the 7th ticket Tom is buying the 6th ticket Tom is buying the 5th ticket Li Si is buying the fourth ticket wang Wu is buying the third ticket Zhang SAN is buying the second ticket Li Si is buying the first ticket Wang Wu is buying the 0 ticket Wang Wu is buying the -1 ticketCopy the code
You can see three people buying 20 tickets. One thread represents one person. Twenty tickets are shared by the three people. But there was something wrong with the program, and someone could buy the 0 ticket, the -1 ticket. Two other people bought the same ticket.
2. Thread status
Threading is a process that executes dynamically, and it also has a process from birth to death.
- New state: new
- Ready state: runnable
- Running status: Running
- The state is blocked
- Execution completed: Dead
The transformation diagram of each state is as follows:
Way to get ready:
- Start () method
- Block lifting
- A thread switches, and the switched thread enters the ready state
- Yield ()—- Comity process
How to enter the blocking state:
- Sleep () method
- The join () method
- Wait () method
Way to enter termination state:
- Normal execution completed
- Destroy () | stop () has been out of date
- Manually check by identifier
1. Sleep ()– The thread sleeps
Function:
- Analog network delay
- Magnify the possibility of problems
However, a thread that goes to sleep using sleep() does not release its own object resources, only CPU resources
Simulate the countdown with the sleep() method
Example 4:
public class Countdown implements Runnable{ public static void main(String[] args) { new Thread(new Countdown()).start(); } @Override public void run() { for(int i=10; i>=0; i--){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if(I ==0){system.out.println ("..."); ); break; } System.out.println(i); }}}Copy the code
The running result of the program is:
10 9 8 7 6 4 3 2 1 Happy New Year...Copy the code
2. Yield ()– Yield to thread
When a thread calls the yield() method, it suspends the currently executing thread object and executes the other threads.
Example 5:
public class YieldDemo implements Runnable{ public static void main(String[] args) { new Thread(new YieldDemo(),"A").start(); new Thread(new YieldDemo(),"B").start(); } @Override public void run() { System.out.println(Thread.currentThread().getName()+"start..." ); Thread.yield(); System.out.println(thread.currentThread ().getName()+"end..." ); }}Copy the code
The running result of the program is:
A:start...
B:start...
A:end...
B:end...
Copy the code
3. Join ()– join thread, queue cutting thread
Example 6:
public class JoinDemo { public static void main(String[] args) { new Thread(new Father()).start(); }} class implements Runnable{@override public void run() {system.out.println (" implements Runnable ") {@override public void run() {system.out.println (" implements Runnable "); ); System.out.println(" Give the son money, let the son buy vinegar.." ); Thread th=new Thread(new Son()); th.start(); try { th.join(); // Thread merge} catch (InterruptedException e) {e.printStackTrace(); System.out.println(" son lost, hurry to find son.." ); } system.out.println (" dumplings in vinegar ~"); }} class Son implements Runnable{@override public void run() {system.out.println (" implements Runnable ") {@override public void run() {system.out. ); System.out.println(" there is a game arcade on the roadside, go to play 10 seconds..." ); for(int i=1; i<=10; i++){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i+"s..." ); } system.out.println (" go and buy vinegar...") ); System.out.println(" Pass daddy the vinegar..." ); }}Copy the code
The running result of the program is:
Eating dumplings without vinegar... Give the son money to buy vinegar.. Took the money, went to buy vinegar... There is a roadside video game city, go to play 10s... 1s... 2s... 3s... 4s... 5s... 6s... 7s... 8s... 9s... 10s... Go get some vinegar... Pass the vinegar to Daddy... Dumplings dipped in vinegar ~Copy the code
3. Thread safety
We see that some people buy the first ticket, some two people buy the same ticket. In this case, thread-safety issues can only occur when multiple threads are operating on the same resource.
To address this security issue, we can control thread safety by synchronizing the synchronized keyword
The keyword synchronized can synchronize methods and blocks.
Synchronous methods can synchronize static methods as well as member methods
Methods for synchronizing blocks:
Synchronized (class | this | resources)} {codeCopy the code
Class the class object of a class a class has only one class object
The synchronization scope is too large and inefficient.
The synchronization range is too small to be locked.
Synchronized is used as a keyword to lock things should be invariable, changed things can not be locked.
Rewrite simulation buying tickets:
Example 7:
public class BuyTikets implements Runnable { @Override public void run() { while (true) { synchronized (Tikets.class) { if (Tikets.tikets <= 0) { break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (thread.currentThread ().getname () + "" + Tikets -- +" "); } } } public static void main(String[] args) { BuyTikets td = new BuyTikets(); New Thread(td, "zhang SAN ").start(); New Thread(td, "三 ").start(); New Thread(td, "w ").start(); } } class Tikets { static int tikets = 20; }Copy the code
The running result of the program is:
John is buying the 20th ticket John is buying the 19th ticket John is buying the 18th ticket John is buying the 17th ticket John is buying the 15th ticket John is buying the 14th ticket John is buying the 12th ticket John is buying the 11th ticket Wang Wu is buying the tenth ticket, Li Si is buying the ninth ticket, Li Si is buying the seventh ticket, Li Si is buying the fifth ticket, li Si is buying the third ticket, Li Si is buying the first ticketCopy the code
This way, there will be no more mistakes in buying tickets.