Day21 multithreading

Posted by sumathi on Tue, 25 Jan 2022 13:29:02 +0100

1. Multithreading

1.1 program, process, thread

Program: a set of commands. In order to complete the specified functions, the program is a static concept and is generally stored in the hard disk

Process: a running program is a dynamic concept and needs to be saved in memory. The operating system will allocate the corresponding PID. When we close a process directly, the process will be destroyed in the running memory

Thread: in a program, different execution branches. If multiple threads are allowed to execute at the same time at the same time node, we call it supporting multithreading

In Java, the main method starts to execute, which is a thread called the main thread

1.2 parallelism and concurrency

Parallel: multiple CPU s execute multiple tasks at the same time

Concurrency: one CPU executes multiple tasks at the same time

Multithreading parallelism requires a CPU greater than or equal to 2

Single core CPU has no multithreading

1.3 single core CPU and multi-core CPU

Single core CPU is actually a fake multithreading, because it can only execute one thread in a time unit. For example: Although there are multiple lanes, there is only one staff member in the toll station charging. Only after charging can it pass through, so the CPU is like a toll collector. If someone doesn't want to pay, the toll collector can "hang" him (hang him until he has figured it out and has the money ready). But because the CPU time unit is very short, I can't feel it.

If it is multi-core, it can give better play to the efficiency of multithreading. (today's servers are multi-core)

A Java application Exe, in fact, there are at least three threads: main() main thread, gc() garbage collection thread and exception handling thread. Of course, if an exception occurs, it will affect the main thread.

1.4 advantages, disadvantages and application scenarios of multithreading

Background: taking a single core CPU as an example, using a single thread to complete multiple tasks successively (calling multiple methods) must take less time than using multiple threads. Why do you still need multiple threads?

Advantages of multithreaded programs:

  1. Improve application response. It is more meaningful to the graphical interface and can enhance the user experience.
  2. Improve the utilization of computer system CPU
  3. Improve program structure. The long and complex process is divided into multiple threads and run independently, which is conducive to understanding and implementation

modify

The program needs to perform two or more tasks at the same time.

When the program needs to realize some tasks that need to wait, such as user input, file reading and writing operation, network operation, search, etc.

When you need some programs running in the background.

1.5 thread creation

1.5.1 Thread

/**
 * The first method is to create a class, inherit the Thread class and override the run method
 * 
 * run Method is the main method in the new thread
 * 
 * @author Dawn Education - handsome and juicy, you zege
 * @Date 2022 At 10:25:31 am on January 24
 */
class Processor extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Test thread-->" + i);
		}
	}
}
	public static void test_01() {
		// Create thread class object
		Thread t1 = new Processor();
		// Call the start method to start the thread
		t1.start();
		for (int i = 0; i < 10; i++) {
			System.out.println("main thread -->" + i);
		}
	}

1.5.2 Runnable

/**
 * The second method is to create a class, implement the Runnable interface, and override the run method
 * 
 * run Method is the main method in the new thread
 * 
 * @author Dawn Education - handsome and juicy, you zege
 * @Date 2022 At 10:30:40 a.m. on January 24
 */
class Processor_01 implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Test thread-->" + i);
		}
	}
}
public static void test_02() {
		// Create implementation class object
		Processor_01 p = new Processor_01();
		// Create thread class object
		Thread t1 = new Thread(p);
		// Start thread
		t1.start();
		for (int i = 0; i < 10; i++) {
			System.out.println("main thread -->" + i);
		}
	}

1.5.3 difference between inheritance and Implementation

 public class Thread extends Object implements Runnable

difference

Inherit Thread: Thread code is stored in the run method of Thread subclass.

Implement Runnable: the run method of the subclass of the interface in the thread code.

Benefits of implementation

The limitation of single inheritance is avoided

Multiple threads can share the object of the same interface implementation class, which is very suitable for multiple threads to process the same resource.

1.6 priorities and common methods

1.6.1 priority overview

Priority level of thread

MAX_PRIORITY: 10

MIN _PRIORITY: 1

NORM_PRIORITY: 5

Methods involved

getPriority(): return thread priority value

setPriority(int newPriority): change the priority of the thread

explain

When a thread is created, it inherits the priority of the parent thread

Low priority is only a low probability of obtaining scheduling, and it is not necessarily called after high priority threads

1.6.2 common methods

 * getName : Gets the name of the thread
 * 
 * setName : Set the name of the thread,If not set,The default is Thread-0 Start increasing in sequence
 * 
 * setPriority() : set priority,java 1 in-10  ,10 Priority levels
 * 			MIN_PRIORITY = 1
 * 			NORM_PRIORITY = 5
 * 			MAX_PRIORITY = 10
 * 
 * getPriority() : Get priority level
 * 
 * static currentThread() : Gets the current thread object
 * 
 * static sleep() : Put the current thread to sleep
 * 
 * currentThread and sleep Is a static method,It means that it has nothing to do with which object call
 * 
 * currentThread : In which thread,Get the object of which thread
 * sleep : In which thread,Just sleep on which thread,Parameter is long Milliseconds of type
 * 

1.6.3 application method

public class Thread_02_Priority {
	public static void main(String[] args) {
		// Create thread object
		Thread t1 = new Processer();
		// set name
		t1.setName("t1");
		// Set priority to 10
		t1.setPriority(10);
		// Set the priority of main to 1
		Thread.currentThread().setPriority(1);
		// Start thread
		t1.start();
		
	
		for (int i = 0; i < 10; i++) {
			try {
				// Sleep for 500 milliseconds
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// Get the thread object and get the thread name
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
	}
}

1.7 life cycle

Thread. Is used in JDK The state class defines several states of a thread

To implement multithreading, you must create a new Thread object in the main Thread. The Java language uses the objects of Thread class and its subclasses to represent threads. In a complete life cycle, it usually experiences the following five states:

New: when the object of a Thread class or its subclass is declared and created, the new Thread object is in the new state

Ready: after the thread in the newly created state is started (), it will enter the thread queue and wait for the CPU time slice. At this time, it has met the running conditions, but it has not been allocated CPU resources

Run: when the ready thread is scheduled and obtains CPU resources, it enters the running state. The run() method defines the operation and function of the thread

Blocking: in a special case, when the input / output operation is suspended or executed artificially, give up the CPU and temporarily suspend its execution to enter the blocking state

Death: the thread completes all its work or the thread is forcibly terminated in advance or ends with an exception

1.8 thread control

1.8.1 thread stop

/**
 * stop : This method is obsolete and is not recommended because it may cause deadlock
 * 
 * Therefore, identifier is generally used to solve the problem
 * 
 * @author Dawn Education - handsome and juicy, you zege
 * @Date 2022 11:06:05 am, January 24
 */
public class Thread_03_Stop {
	public static void main(String[] args) {
		Processer_03 p = new Processer_03();
		Thread t1 = new Thread(p);
		t1.setName("t1");
		t1.start();

		try {
			Thread.sleep(5000);
			// t1.stop();
			p.flag=true;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
class Processer_03 implements Runnable {
	// Add an identifier to identify whether to terminate the thread
	boolean flag = false;

	@Override
	public void run() {
		for (int i = 0; true; i++) {
			// Determine whether to terminate
			if (flag) {
				System.out.println(Thread.currentThread().getName() + "The thread has been terminated");
				return;
			}
			try {
				Thread.sleep(1000);
				System.out
						.println(Thread.currentThread().getName() + "-->" + i);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

1.8.2 thread merging

* join : Thread merging,Let the current thread wait for the specified thread to finish executing,Then continue the execution
 */
public class Thread_04_Join {
	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Processer_04();
		t1.setName("t1");
		t1.start();
		// At this point, main will wait for the t1 thread to execute before continuing
		t1.join();
		for (int i = 0; i < 10; i++) {
			try {
				// Sleep for 500 milliseconds
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			// Get the thread object and get the thread name
			System.out.println(Thread.currentThread().getName() + "-->" + i);
		}
	}
}

1.8.3 Yield

 * yield : Static method,Pauses the currently executing thread object,And execute other waiting threads
 * 
 * 1 Static method,It means that there is no official thanks for calling with that object,In which thread,Which thread gives way
 * 
 * 2 Give way to the same priority,Different priorities do not give way
public class Thread_05_Yield {
	public static void main(String[] args) {
		// Create thread
		Thread t1 = new Thread(new Processor_05());
		t1.setName("t1");
		// Set the priority of t1 thread and main thread to be consistent
		t1.setPriority(5);
		Thread.currentThread().setPriority(5);
		// start-up
		t1.start();
		for (int i = 0; i < 10; i++) {
			// Give way
			Thread.yield();
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
	}
}

1.9 thread synchronization

1.9.1 general

Raising questions

The uncertainty of multi thread execution leads to the instability of execution results

The sharing of ledger by multiple threads will cause the incompleteness of operation and destroy the data

 

 * Thread synchronization : When multiple threads may operate on the same data at the same time,To ensure data consistency,Synchronous execution is required
 * 
 * The essence is to synchronize data,Is a security mechanism
 * 
 * Asynchronous programming : Threads are completely independent,No mutual influence
 * 
 * Synchronous programming : Threads are not completely independent,May influence each other
 * 
 * Synchronized scene : 1 Must be multithreaded(Concurrency is required,It's possible to make mistakes) 2 The possibility that multiple threads may operate on the same data at the same time 3
 * In particular, change the data at the same time,Query doesn't matter

1.9.2 problems caused by out of synchronization

// Entity class
class Account {
	// balance
	private double balance;

//	public synchronized void withDraw(double money) {
	public   void withDraw(double money) {
		// If synchronized is added to the method, there can only be one thread executing the method
		System.out.println(Thread.currentThread().getName() + " Yes");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// Statement block lock
		synchronized (this) {
			// Balance minus withdrawal amount
			double after = balance - money;
			// Copy new balance to balance
			balance = after; // 2000
			System.out.println(Thread.currentThread().getName() + " Successful withdrawal,withdraw money : "
					+ money + "element,surplus : " + balance + " element ");
		}
	}

	public Account(double balance) {
		super();
		this.balance = balance;
	}

	public Account() {
		super();
	}

	public double getBalance() {
		return balance;
	}

	public void setBalance(double balance) {
		this.balance = balance;
	}

}
// Thread class
class Processor_06 extends Thread {
	// account
	Account act;
	
	public Processor_06(Account act) {
		this.act = act;
	}

	@Override
	public void run() {
		// Take 1000
		act.withDraw(1000);
	}
}
public class Thread_06_Synchroinzation {
	public static void main(String[] args) {
		// Create an account with a balance of 3000
		Account act = new Account(3000);
		// Two threads, 1000 for each
		Thread t1 = new Processor_06(act);
		Thread t2 = new Processor_06(act);
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		t2.start();
	}
}

 

1.9.3 solution

1.9.3.1 method lock

After the method uses synchronized, the method can only have one thread to execute

1.9.3.2 statement block lock

If only part of the code needs to be synchronized in this method, the efficiency will be greatly reduced if it is modified by synchronized

Therefore, we can lock only the corresponding code through the statement block lock. In this way, other codes in the method can be executed at the same time, and the efficiency is improved

 1.9.4 Synchronized

* synchronized(object){} Member statement block lock
 * 
 * When accessing a locked member method or member statement block lock in an object,Then all locked member methods and member statement block locks in the object are locked
 * 
 * synchronized(Class name.class){} Static statement block lock
 * 
 * When accessing a class,When locking static methods or static statement blocks,Then all static methods and static statement block locks locked in the object are locked
// Business class
class MyClass_01 {
	public synchronized void m1() {
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Locked m1 method");
	}

	public synchronized void m2() {
		System.out.println("Locked m2 method");
	}

	public void m3() {
		System.out.println("Unlocked m3 method");
	}
}
class Processor_08 implements Runnable {
	MyClass_01 mc;

	public Processor_08(MyClass_01 mc) {
		this.mc = mc;
	}

	@Override
	public void run() {
		// Get thread name
		String name = Thread.currentThread().getName();
		if (name.equals("t1")) {
			mc.m1();
		} else if (name.equals("t2")) {
			mc.m2();
		}
		if (name.equals("t3")) {
			mc.m3();
		}
	}
}
public class Thread_07_Synchroinzation {
	public static void main(String[] args) {
		MyClass_01 mc = new MyClass_01();
		Thread t1 = new Thread(new Processor_08(mc));
		Thread t2 = new Thread(new Processor_08(mc));
		Thread t3 = new Thread(new Processor_08(mc));
		t1.setName("t1");
		t2.setName("t2");
		t3.setName("t3");
		t1.start();
		// Ensure that t1 executes first and enter m1 method to execute sleep
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t2.start();
		t3.start();
		// Execute m3 after 1 second and m1 and m2 after 3 seconds
	}
}

1.10 Lock

1.10.1 general

Starting with JDK 5.0, Java has provided a more powerful thread synchronization mechanism -- by explicitly defining the same thread

Step Lock object to achieve synchronization. Synchronous locks use Lock objects as.

java.util.concurrent.locks.Lock interface is a tool that controls multiple threads to access shared resources. Locks provide exclusive access to shared resources. Only one thread can lock the lock object at a time. Threads should obtain the lock object before accessing shared resources.

ReentrantLock class implements Lock. It has the same concurrency and memory semantics as synchronized. ReentrantLock is commonly used in thread safety control, which can explicitly add and release locks.

1.10.2 use

// Entity class
class Account1 {
	// balance
	private double balance;

	// Create lock object
	Lock lock = new ReentrantLock();
	
	public void withDraw(double money) {
		System.out.println(Thread.currentThread().getName()+" Come in");
		// Start synchronization
		lock.lock();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// Statement block lock
		// Balance minus withdrawal amount
		double after = balance - money;
		// Copy new balance to balance
		balance = after; // 2000
		System.out.println(Thread.currentThread().getName() + " Successful withdrawal,withdraw money : "
				+ money + "element,surplus : " + balance + " element ");
		// Unlock
		lock.unlock();
	}

	public Account1(double balance) {
		super();
		this.balance = balance;
	}

	public Account1() {
		super();
	}

	public double getBalance() {
		return balance;
	}

	public void setBalance(double balance) {
		this.balance = balance;
	}

}

1.10.3 advantages and disadvantages

 * lock Yes display lock,Manual opening and closing required  synchronized Is an implicit lock,Automatic opening,Auto close after execution
 * 
 * lock Only code block locks , and synchronized Support method and code block lock
 * 
 * lock lock,need JVM Spend less time on resource scheduling.Relatively good performance,And it has good scalability
 * 
 * Order of use : Lock lock ---> Synchronous code block lock ---> Method lock

1.11 timer tasks

1.11.1 general

 * timer : Planning tasks
 * 
 * As long as there is a planned task,A thread will start,Timing,After reaching the specified time,This thread completes this task

1.11.2 use

public class Thread_09_Timer {
	public static void main(String[] args) {
		// 1. What to do is the task object
		// 2 when to start, 1000 * 5 is 5 seconds later
		// 3 interval. How often do you do 1000 * 3 every 3 seconds
		Timer t = new Timer();
		t.schedule(new LogTimerTask(), 1000*5,1000*3);
	}
}

// Create task
class LogTimerTask extends TimerTask {
	@Override
	public void run() {
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = sdf.format(date);
		System.out.println(time);
	}
}

Topics: Java Back-end