Multithreading Foundation

Posted by pplexr on Wed, 26 Jan 2022 18:08:27 +0100

I Multithreading

  1. definition
    • process
      • A process is a path for program execution
      • A system level application execution is a process
    • thread
      • Threads are inside a process. There can be multiple threads in a process
      • Concurrent execution of multiple threads can improve the efficiency of the program and complete multiple tasks at the same time
      • Multithreading saves the waiting time of executing programs. If the programs are closely arranged and there is no waiting time, multithreading can not really improve the efficiency
  2. Multithreaded applications
    • Thunderbolt downloads multiple tasks
    • The server processes multiple requests at the same time
  3. The difference between multithreading concurrency and parallelism
    • Parallel means that two tasks are running at the same time, that is, task a is running while Task B is also running (multi-core CPU is required)
    • Concurrency means that two tasks are requested to run, and the processor can only accept one task, so the two tasks are arranged in turn. Due to the short time interval, people feel that both tasks are running
    • For example, I chat with two netizens. My left hand operates one computer to chat with a, and my right hand uses another computer to chat with B. This is called parallelism
    • If I use a computer, I first send a message to a, then immediately send a message to B, then talk to a, and then talk to B. This is called concurrency
  4. Java virtual machine running process
    • The java command will start the java virtual machine and the JVM, which is equivalent to starting an application, that is, starting a process. The process will automatically start a "main thread", and then the main thread will call the main method of a class
    • At least a garbage collection thread and a main thread are created after the JVM is started
  5. reflection
    • Which is more efficient, a quad core CPU or a dual core Quad thread CPU?

II Implementation of multithreading in JAVA

  1. step

    • Inherit Thread mode
    • Define class inheritance Thread
    • Override run method
    • Write what the new thread wants to do in the run method
    • Create thread object
    • Call the start() method to start a new thread, and the run method will be automatically executed internally
  2. demonstration

public class MyThread extends Thread{

@Override-
public void run() {
	while(true){
		System.out.println("I'm a child thread");
	}
}

}

```java
public static void main(String[] args) {
	
	MyThread myThread = new MyThread();
	myThread.start();
}
  1. Principle analysis

    • Creating multithreading must deal with the bottom layer of the system platform. Our program doesn't know how to do it at all. All we just provide running code. How to create multithreading depends on java
    • Inherit the form of Thread. Only one Thread can be created for each subclass object of Thread
  2. Test questions

    • Start multiple threads at the same time to print different statements

III Implementation mode 2 of multithreading in JAVA

  1. step

    • Define a class to implement the Runnable interface
    • Implement run method
    • Write what the new thread wants to do in the run method
    • Create a subclass object of a custom Runnable
    • Create a Thread object and pass in Runnable
    • Call start() to start a new thread, and the run() method of Runnable will be automatically called internally
  2. demonstration

    public class MyRunnable implements Runnable{
    
    	@Override
    	public void run() {
    		while(true){
    			System.out.println("I'm a child thread");
    		}
    	}
    }
    
    public static void main(String[] args) {
    	
    	MyRunnable myRunnable = new MyRunnable();
    
    	Thread thread = new Thread(myRunnable);
      	Thread thread2 = new Thread(myRunnable);
    	thread.start();
      	thread2.start();	
    }
    
  3. principle

    • A Runnable type member variable target is defined in the Thread class to receive Runnable subclass objects
    • When the start() method of the Thread object is called, the method first determines whether the target is null If it is not null, call the run method of the Runnable subclass object
    • Multiple Thread objects can share a Runnable subclass object
  4. Test questions

    • Define an int member variable num in MyThread and MyRunnable, and use this variable as the control condition of the loop
    • Customize the print statement, use these two methods to create two threads in the main thread, and turn on multithreading
    • Customize the value of the variable num to print 10 statements in two ways of creating multithreading

IV The difference between two methods of multithreading

  1. See the difference between source code:
    • Inherit Thread: since the subclass overrides the run() of the Thread class, when calling start(), directly find the run() method of the subclass
    • Implementation of Runnable: the reference of Runnable is passed in the constructor, and the member variable remembers it. When start() calls the run() method, it internally judges whether the reference of the member variable Runnable is empty. If it is not empty, the run() of Runnable is viewed during compilation, and the run() method of subclass is executed during runtime
  2. Inherit Thread
    • The advantage is: you can directly use the methods in the Thread class, and the code is simple
    • The disadvantage is: if you already have a parent class, you can't use this method
  3. Implement Runnable interface
    • The advantage is: it doesn't matter even if the thread class you define has a parent class, because the parent class can also implement the interface, and the interface can be implemented in multiple ways. Multiple threads can easily use the member variables of the same object
    • The disadvantage is that you can't directly use the method in Thread. You need to get the Thread object before you can get the method of Thread. The code is complex
  4. reflection
    • When we call the start() method, does it mean that the thread runs immediately?
    • cpu execution right (time slice): if the current thread is executed by the cpu, we say that the current thread has obtained the execution right of the cpu
    • After calling the start method, it means that the current thread is ready to be executed

V Two ways to implement multithreading by anonymous inner classes

  1. Inherit Thread class

    public static void main(String[] args) {
    	
    	new Thread(){
    		public void run(){
    			while(true){
    				System.out.println("I'm a child thread");
    			}
    		}
    	}.start();
    	
    }
    
  2. Implement Runnable interface

    public static void main(String[] args) {
    	//Create Thread object and provide Runnable anonymous inner class object
    	new Thread(new Runnable(){
    		public void run(){
    			while(true){
    				System.out.println("I'm a child thread");
    			}
    		}
    	}).start();
    }
    

Vi Get name and set name in multithreading

  1. Get name

    • Get the name of the thread object through the getName() method
    • This method is only applicable to the form of Thread
    • The form of Runnable must obtain the name by obtaining the thread object
  2. demonstration

    public class MyThread extends Thread{
    
    	@Override
    	public void run() {
    		
    		System.out.println(this.getName());
    	
        }
    }
    
  3. Set name

    • Pass in the name of the String type through the constructor

      public static void main(String[] args) {
        
      	new Thread("Thread one"){
      		public void run(){
      			
      			System.out.println(this.getName());
      		}
      	}.start();
      }
      
    • The name of the thread object can be set through the setName method

      public static void main(String[] args) {
      	
      	Thread thread1 = new Thread("Thread one"){
      		public void run(){
      			
      			System.out.println(this.getName());
      		}
      		
      	};
      	thread1.setName("Thread one");
      	thread1.start();
      }
      

VII Gets the object of the current thread

  1. definition

    • We can get the object representing the current executing thread in the multithreaded running code and operate on it
  2. demonstration

    • View the name of the current thread in the Runnable running code in the form of an object

      public static void main(String[] args) {
      	
      	new Thread(new Runnable() {
      		
      		@Override
      		public void run() {
                	 //Gets the name of the thread
      			System.out.println(Thread.currentThread().getName());
      			
      		}
      	}).start();
      
      }
      
    • Set the name of the thread by getting the thread object

      public static void main(String[] args) {
      	
      	new Thread(new Runnable() {
      		@Override
      		public void run() {
      			Thread.currentThread().setName("Thread two");//Sets the name of the thread
      			System.out.println(Thread.currentThread().getName());
      		}
      	}).start();
      }
      
    • Set the name of the Thread through the construction method of Thread

      public static void main(String[] args) {
      	
      	new Thread(new Runnable() {
      		
      		@Override
      		public void run() {
      			
      			System.out.println(Thread.currentThread().getName());
      			
      		}
      	//Set the name of the thread through the constructor
      	},"Thread two").start();
      
      }
      

VIII Sleep thread

  1. definition

    • Call Thread. in the execution code of the thread Sleep () method, you can sleep the thread for several milliseconds
    • The thread whose sleep ends enters the runnable state instead of running directly
  2. demonstration

    public static void main(String[] args) {
      
    	new Thread(new Runnable() {
    		@Override
    		public void run() {
    			
    			long time1 = System.currentTimeMillis();
    			System.out.println(time1);
    			
    			try {
    				Thread.sleep(10000);//Set the thread to wait 10000 milliseconds
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			
    			long time2 = System.currentTimeMillis();
    			System.out.println(time2);
    		}
    	//Set the name of the thread through the constructor
    	}).start();
    
    }
    
  3. Test questions (tortoise and rabbit race)

    • Requirements: the total race distance of tortoise and rabbit is 100m, the speed of rabbit is 10m/s, and the speed of tortoise is 5m/s. both tortoise and rabbit output the results every 10m. When the rabbit runs 70m, rest for 2s and program to simulate the race process

IX Daemon thread

  1. definition

    • Running around other non daemon threads, the thread will not run alone. When the execution of other non daemon threads ends, it will exit automatically
    • Call the setDaemon() method of Thread to set a Thread as a daemon Thread
  2. Application scenario

    • When using feiqiu chat, we open multiple chat windows. When we close the main program, all other chat windows will be closed
  3. demonstration

    public static void main(String[] args) {
    	
    	Thread t1 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 5; i++) {
    				System.out.println("Thread 1 running");
    			}
    		}
    	});
    	
    	Thread t2 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Daemon thread running..........");
    			}
    		}
    		
    	});
    	
    	t2.setDaemon(true);
    	t1.start();
    	t2.start();
    
    }
    

X Join thread

  1. definition

    • The current thread is suspended. Wait until the execution of the specified thread is completed, and then the current thread continues
  2. common method

    • join() takes precedence over the specified thread
    • Join (MS) takes precedence over the specified thread for several milliseconds
  3. demonstration

    public static void main(String[] args) {
    	
    	Thread t1 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 1 running");
    				try {
    					Thread.sleep(10);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		
    	});
    	
    	Thread t2 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 2 is running..........");
    				try {
    					t1.join(); //Let the thread execute first
    					t1.join(100);//Let the thread execute for 100 milliseconds first
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				try {
    					Thread.sleep(10);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		
    	});
    	
    	//Only the thread that calls the join thread will stop running, and other threads will not be affected
    	Thread t3 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 3 is running..........");
    				try {
    					Thread.sleep(10);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		
    	});
    	
    	t1.start();
    	t2.start();
    	t3.start();
    
    }
    
  4. matters needing attention

    • Only the thread that calls the join method of other threads will stop running, and other threads will not be affected

Xi Comity thread (understand)

  1. definition

    • Relinquish the execution right of the current thread
    • Basically no effect can be seen
  2. demonstration

    public static void main(String[] args) {
    	
    	Thread t1 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 1 running");
    			}
    		}
    		
    	});
    	
    	Thread t2 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 2 is running..........");
    				//Relinquish the execution right of the current thread
    				Thread.yield();
    				
    			}
    		}
    	});
    
    	t1.start();
    	t2.start();
    }
    

XII Set thread priority

  1. definition

    • Each thread has a priority. The default is 5. The range is 1-10. 1 indicates the lowest priority
    • High priority threads have certain advantages in competing for the execution right of cpu, but they are not absolute
  2. demonstration

    public static void main(String[] args) {
    	
    	Thread t1 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 1 running");
    				
    			}
    		}
    		
    	});
    	
    	Thread t2 = new Thread(new Runnable() {
    		
    		@Override
    		public void run() {
    			
    			for (int i = 0; i < 50; i++) {
    				System.out.println("Thread 2 is running..........");
    				
    			}
    		}
    	});
    	
    	t1.setPriority(1);
    	t2.setPriority(10); //Thread 2 has high priority
    	t1.start();
    	t2.start();
    }
    

XIII Multithreading security issues

  1. definition

    • When multiple threads operate on the same data, because of the randomness of thread execution, thread safety problems may occur
    • This problem can be solved by using synchronization. The code that operates the data can be synchronized. Only one thread can operate the data at the same time to ensure the security of the data
  2. Thread safety demonstration

    public static void main(String[] args) {
    	
    	Thread t1 = new Thread(){
    		public void run(){
    			while(true){
    				
    				if (num>0) {
    					System.out.println(getName()+":"+num--);
    				}else{
    					break;
    				}
    			}
    		}
    	};
    	Thread t2 = new Thread(){
    		public void run(){
    			while(true){
    				
    				if (num>0) {
    					System.out.println(getName()+":"+num--);
    				}else{
    					break;
    				}
    				
    			}
    		}
    	};
    	t1.start();
    	t2.start();
    }
    
  3. Solve security problems

    • Lock some code with the synchronized keyword

      public static void main(String[] args) {
      	
      	Thread t1 = new Thread(){
      		public void run(){
      			while(true){
      				//Lock
      				synchronized (Class.class) {
      					if (num>0) {
      						System.out.println(getName()+":"+num--);
      					}else{
      						break;
      					}
      				}
      
      			}
      		}
      	};
      	Thread t2 = new Thread(){
      		public void run(){
      			while(true){
      				//Add a unified lock
      				synchronized (Class.class) {
      					if (num>0) {
      						System.out.println(getName()+":"+num--);
      					}else{
      						break;
      					}
      				}
      			}
      		}
      	};
      	t1.start();
      	t2.start();
      }
      
    1. matters needing attention
      • Code that uses the same lock can be synchronized
      • A thread that does not acquire a lock cannot run even if it has the execution authority of the cpu
      • Minimize the range of locks to avoid inefficiency
      • Locks can be added to the code or methods of any class
    2. Test questions
      • There are a total of 100 tickets in the railway station. Four windows sell tickets at the same time. When the tickets are sold out, it will prompt "no tickets..." and program the simulation scene

XIV deadlock

  1. definition

    • Multiple threads using synchronization hold the resources required by each other's runtime at the same time
    • When multiple threads are synchronized, multiple synchronized code blocks are nested, which is easy to cause deadlock
    • The more locks are nested, the easier it is to cause deadlock
  2. demonstration

    • Thread 1 needs to get the left chopsticks first, and then get the right chopsticks before eating
    • Thread 2 needs to get the chopsticks on the right first, and then get the chopsticks on the left before eating
    • When thread 1 holds the chopsticks on the left and thread 2 holds the chopsticks on the right, they wait for each other to release the lock, but they also hold the conditions for each other to release the lock. If they do not give in to each other, they will cause infinite waiting
    private static String s1 = "Chopsticks left";
    private static String s2 = "Chopsticks right";
    
    public static void main(String[] args) {
    	new Thread() {
    		public void run() {
    			while(true) {
    				synchronized(s1) {
    					System.out.println(getName() + "...Get" + s1 + "wait for" + s2);
    					synchronized(s2) {
    						System.out.println(getName() + "...Get" + s2 + "Eat");
    					}
    				}
    			}
    		}
    	}.start();
    	
    	new Thread() {
    		public void run() {
    			while(true) {
    				synchronized(s2) {
    					System.out.println(getName() + "...Get" + s2 + "wait for" + s1);
    					synchronized(s1) {
    						System.out.println(getName() + "...Get" + s1 + "Eat");
    					}
    				}
    			}
    		}
    	}.start();
    }
    

Topics: Java Back-end Multithreading