1. Three methods of creating threads
- Inherit Thread class [key]
- Inherit the Thread class, override the run() method, and call start to start the Thread
- Not recommended: avoid the limitation of OOP single inheritance
//Method 1 of creating a Thread: inherit the Thread class, rewrite the run() method, and call start to start the Thread public class Thread_one extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Thread_one......"); } } public static void main(String[] args) { //Create a thread object Thread_one thread = new Thread_one(); //Calling the strat() method calls the thread thread.start(); for (int i = 0; i < 1000; i++) { System.out.println("main......"); } } }
- Implementation of Runnable interface [ key ]
- Implement the runnable interface and rewrite the run method. The execution thread needs to drop into the runnable interface implementation class and call the start method
- Recommended: it avoids the limitation of single inheritance, is flexible and convenient, and is convenient for the same object to be used by multiple threads
//The second way to create a thread: implement the runnable interface and rewrite the run method. The execution thread needs to throw in the runnable interface implementation class and call the start method public class Thread_two implements Runnable{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("Thread......."); } } public static void main(String[] args) { Thread_two thread_runnable = new Thread_two(); Thread thread = new Thread(thread_runnable); thread.start(); for (int i = 0; i < 1000; i++) { System.out.println("main......"); } } }
- Implement Callable interface [understand]
- Implement the call method in the Callalbe interface. Create an execution service, submit execution, obtain results, and close the service.
//The third way to create a thread is to implement the call method in the callalbe < T > interface. Create an execution service, submit execution, obtain results, and close the service. public class Thread_three implements Callable<Boolean>{ private String name; public Thread_three(String name) { this.name = name; } @Override public Boolean call() throws Exception { for (int i = 0; i < 20; i++) { System.out.println(this.name +"Yes..."); } return true; } public static void main(String[] args) { Thread_three t1 = new Thread_three("t1"); Thread_three t2 = new Thread_three("t2"); Thread_three t3 = new Thread_three("t3"); //Create execution service ExecutorService ser = Executors.newFixedThreadPool(3); //Submit for execution Future<Boolean> r1 = ser.submit(t1); Future<Boolean> r2 = ser.submit(t2); Future<Boolean> r3 = ser.submit(t3); //Get results try { boolean rs1 = r1.get(); boolean rs2 = r2.get(); boolean rs3 = r3.get(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } //Shut down service ser.shutdown(); } }
2. Thread method
- Thread five states: creation state, ready state, running state, blocking state and death state
- Thread method
method | explain |
---|---|
setPriority(int newPriority) | Change the priority of a thread |
static void sleep(long millis) | Hibernates the currently executing thread for the specified number of milliseconds |
void join() | Wait for the thread to terminate |
static void yield | Pauses the currently executing thread object and executes other threads |
void interrupt | Interrupt the thread. Don't do it this way |
boolean isAlive | Test whether the thread is active |
- Thread stop
/** * Thread stop * 1. It is recommended that the thread stop normally -- > utilization times, and dead loop is not recommended * 2. It is recommended to use flag bit -- > to set a flag bit * 3. Do not use outdated methods such as stop or destroy, or methods that are not recommended by JDK */ public class Thread_stop implements Runnable{ //Set a flag bit private boolean flag = true; @Override public void run() { int i = 0; while(flag) { System.out.println("run ---> thread" + i++); } } public void stop() { this.flag = false; } public static void main(String[] args) { Thread_stop stop = new Thread_stop(); for (int i = 0; i < 1000; i++) { if(i == 900) { stop.stop(); System.out.println("The thread stopped......"); } } } }
3. Daemon thread
- The virtual machine must ensure that the user thread has completed execution
- The virtual machine does not have to wait for the daemon thread to complete execution, such as garbage collection, memory monitoring, etc
Thread thread = new Thread() thread.setDaemon(true) //Open daemon thread
4. Thread synchronization
- Thread synchronization: multiple threads operate on the same resource.
- Thread synchronization is actually a waiting mechanism. Multiple threads that need to access this object at the same time enter the waiting pool of this object to form a queue, wait for the previous thread to use it, and then use it again for the next thread.
- Locking mechanism synchronized
Synchronization method and synchronization code block
public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket station = new BuyTicket(); new Thread(station, "a").start(); new Thread(station, "b").start(); new Thread(station, "c").start(); } } class BuyTicket implements Runnable{ //ticket private int ticketNums = 10; boolean flag = true; @Override public void run() { //Buy a ticket while(flag) { try { buy(); } catch (Exception e) { e.printStackTrace(); } } } //Synchronized: the synchronized method locks this private synchronized void buy() throws InterruptedException{ //Judge whether there are tickets if(ticketNums <= 0) { flag = false; return; } //Analog delay Thread.sleep(100); //Buy a ticket System.out.println(Thread.currentThread().getName() + "Get" + ticketNums--); } //Synchronized: synchronized code blocks. The lock is the amount of change private void buy_() throws InterruptedException{ synchronized(ticketNums) { //Judge whether there are tickets if(ticketNums <= 0) { flag = false; return; } //Analog delay Thread.sleep(100); //Buy a ticket System.out.println(Thread.currentThread().getName() + "Get" + ticketNums--); } } }
Locking mechanism
import java.util.concurrent.locks.ReentrantLock; public class Lock { public static void main(String[] args) { testLock lock = new testLock(); new Thread(lock).start(); new Thread(lock).start(); new Thread(lock).start(); } } class testLock implements Runnable { int ticketNums = 10; //Define lock lock private final ReentrantLock lock = new ReentrantLock(); @Override public void run() { while(true) { try { //Lock lock.lock(); if(ticketNums > 0) { try { Thread.sleep(1000); System.out.println(ticketNums--); } catch (Exception e) { e.printStackTrace(); } }else { break; } }finally{ //Unlock lock.unlock(); } } } }
Priority of locks: lock mechanism > sync code block > sync method
5. Thread communication
- Several methods of thread communication
Method name | effect |
---|---|
wait() | It means that the thread has been waiting and knows that other threads notify it. Unlike sleep, it will release the lock |
wait(long timeout) | Specifies the number of milliseconds to wait |
notify() | Wake up a waiting thread |
notifyAll() | Wake up all threads calling the wait() method on the same object, and the threads with high priority are scheduled first |
- Solutions to producer consumer problems
- Pipe process method: the producer puts the produced data into the buffer, and the consumer takes out the data from the buffer
public class Pc { public static void main(String[] args) { SynContainer container = new SynContainer(); new Productor(container).start(); new Consumer(container).start(); } } //producer class Productor extends Thread { SynContainer container; public Productor(SynContainer container) { this.container = container; } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Produced" + i + "Chicken"); container.push(new Chicken(i)); } } } //consumer class Consumer extends Thread { SynContainer container; public Consumer(SynContainer container) { this.container = container; } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Consumption-->" + container.pop().id + "Chicken"); } } } //product class Chicken { int id;//Product number public Chicken(int id) { this.id = id; } } //buffer class SynContainer { Chicken[] chickens = new Chicken[10]; int count = 0; //The producer puts in the product public synchronized void push(Chicken chicken) { //If the container is full, it needs to wait for consumers to consume if(count == chickens.length) { //Inform consumers of consumption. Production waiting try { this.wait(); } catch (Exception e) { e.printStackTrace(); } } //If it is not full, we need to throw in the product chickens[count] = chicken; count++; //Consumers can be informed of consumption this.notifyAll(); } //Consumer products public synchronized Chicken pop() { //Judge whether it can be consumed if(count == 0) { //Wait for producers to generate, consumers to wait try { this.wait(); } catch (Exception e) { e.printStackTrace(); } } //If you can consume count--; Chicken chicken = chickens[count]; //When finished, inform the producer to produce this.notifyAll(); return chicken; } }
- Signal lamp method
public class Pc2 { public static void main(String[] args) { TV tv = new TV(); new Player(tv).start(); new Watcher(tv).start(); } } //Producer -- > actor class Player extends Thread { TV tv; public Player(TV tv) { this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if(i % 2 == 0) { this.tv.play("Central one"); }else { this.tv.play("Central five sets"); } } } } //Consumer -- > audience class Watcher extends Thread { TV tv; public Watcher(TV tv) { this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { tv.watch(); } } } //Products -- > Programs class TV { //The audience waited while the actors performed //The audience watched and the actors waited String voice; //A performance boolean flag = true; //perform public synchronized void play(String voice) { if(!flag) { try { this.wait(); } catch (Exception e) { e.printStackTrace(); } } System.out.println("The actors performed:" + voice); //Inform the audience to watch this.notifyAll(); this.voice = voice; this.flag = !this.flag; } //watch public synchronized void watch() { if(flag) { try { this.wait(); } catch (Exception e) { e.printStackTrace(); } } System.out.println("The audience watched:" + voice); //Notice performance this.flag = !this.flag; } }
6. Thread pool
- Create multiple threads in advance, put them into the thread pool, obtain them directly when using them, and put them back into the pool after use. It can avoid frequent creation, destruction and reuse.
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Pool { public static void main(String[] args) { //1. Create thread pool ExecutorService service = Executors.newFixedThreadPool(10); //2. Using threads service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); //3. Close the connection service.shutdown(); } } class MyThread implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + i); } } }