1. Basic concepts
1.1 distinction among programs, processes and threads:
Program
The essence is a piece of static code and static object.
Process
An execution of a program, or a running program, is a dynamic process.
Process is the unit of resource allocation. The system will allocate different memory areas for each at run time.
Thread
Thread is the unit of scheduling and execution. Each thread has an independent running stack and program counter (PC).
Multiple threads in a process share the same memory unit / memory address space.
Threads in a process can access the same variables and objects.
Note: Java application Exe has at least three threads: main main thread, gc garbage collection thread and exception handling thread.
1.2 parallelism and concurrency
Parallel: multiple CPU s execute multiple tasks at the same time
Concurrency: one CPU (split time slice) executes multiple tasks at the same time
2. Thread creation and startup
2.1Thread class (java.lang.Thread)
Constructor:
Thread(): creates a thread object
Thread(String threadname): create a process and specify the process name
Thread (Runnable target): the process that creates the specified target object, which implements the run method of the Runnable interface
Thrad(Runnable target,String name): create the process of the specified object and specify the name
attribute
static int MAX _PRIORITY ¢ attribute value: 10 ¢ maximum priority
static int MIN _PRIORITY ¢ attribute value: 1 ¢ minimum priority
static int NORM _PRIORITY ¢ attribute value: 5 ¢ normal priority
Method name
static Thread currentThread(): returns the current thread
static void yield(): thread yielding to a higher priority thread
static void sleep(long mills): the thread waits, but an InterruptedException exception will be thrown
void stop(): obsolete, forcing the current thread to stop
void run(): the method to be overridden by the subclass
void start(): start and call the run() method
void join(): calling thread B's join() in thread A will block thread A until thread B completes execution.
boolean isAlive(): judge whether the thread is still running
Boolean islntruopted(): judge whether the thread is interrupted
int getPriority(): return thread priority
viod setPriority(int priority): sets thread priority
String getName(): returns the thread name
void setName(String name): set the name
2.3 thread classification
Threads in Java are divided into user threads and daemon threads. The main thread is the user thread, and the gc thread is the guard thread,
The daemon thread will depend on the user thread. When the user thread finishes executing, the daemon thread will also stop executing.
User threads can be set as daemon threads through setDaemon(true). When there are daemon threads in the JVM, the current JVM will exit.
2.4 ways to create threads
There are four ways to create threads, and the last two are in jdk5 Add after 0.
2.4. 1. Inherit Thread class (java.lang.Thread)
The defined subclass inherits the Thread class
Override the run method of Thread class in subclass
Create a thread object and call the start method of the object to start the thread (execute the run method)
Note:
If you call the run method manually, it is just a normal method, not a multithreaded mode
The actual method is called by the JVM
A thread object can only call the start method once. If it is called repeatedly, an exception "Iegal Thread State Exception" will be thrown
2.4. 2. Implement the Runnable interface (java.lang.runnable)
Q: why implement the Runnable interface?
-Java does not support multi inheritance- It is not intended to override other methods of the Thread class.
Define a class to implement the Runnable interface
1 package com.imooc.runnable; 2 class PrintRunnable implements Runnable{ 3 /* 4 * (non-Javadoc) 5 * @see java.lang.Runnable#run() 6 * Core operation 7 * 1.Define a Class A to implement the Runnable interface 8 * 2.Implement the run method in Runnable 9 * 3.Runnable Cannot use getName() method directly 10 * A static method that needs to call Thread is Thread currentThread(), which represents the current Thread, and then calls the gatName() method 11 * Thread.currentThread().getName(); 12 * 4.In the main method, first define the object B of class A. class a cannot directly call the start() method. The starting Thread can only be Thread and its subclasses 13 *Therefore, first create the Thread object C and use B as the parameter Thread t1 = new Thread(pr); 14 */ 15 @Override 16 public void run() { 17 int i=1; 18 while(i <= 10) 19 System.out.println(Thread.currentThread().getName()+"Running!"+(i++)); 20 21 } 22 23 } 24 public class Test { 25 26 public static void main(String[] args) { 27 PrintRunnable pr = new PrintRunnable(); 28 Thread t1 = new Thread(pr); 29 t1.start(); 30 PrintRunnable pr1 = new PrintRunnable(); 31 Thread t2 = new Thread(pr1); 32 t2.start(); 33 } 34 35 }
The implementation class needs to override the run method of the Runnable interface
Pass the object of the implementation class as a parameter to the constructor of the Thread class to create a Thread object.
Call the start method of the thread object (start the thread and call the run method of the current thread)
2.4. 3. Implement the callable interface (java.util.concurrent.Callable)
Callable interface
The Callable interface is more powerful than the Runnable interface. Classes that implement the Callable interface need to override the call() method.
The call() method supports generic return values, can throw exceptions, and can obtain the return results with the help of Future Task.
Future interface (java.util.concurrent.Future)
You can cancel the execution results of specific runnable and callable tasks, query whether they are completed, and obtain results
The FutureTask class is the only implementation class of the Future interface.
The FutureTask class is the only implementation class of the Future interface.
FutureTask class implements both Runnable interface and Future interface. It can be executed by the thread as Runnable or callable as Future The return value of call().
2.4. 4. Using thread pool
Background
Resources that are often created and destroyed and used heavily, such as threads in concurrency, have a great impact on performance.
Train of thought
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. Frequent creation can be avoided
Destroy and realize reuse. Similar to public transport in life.
Benefits
Improve reuse. Similar to public transport in life.
Reduce resource consumption (reuse threads in the thread pool and do not need to be created every time)
Easy thread management
ExecutorService: thread pool interface. The common implementation class ThreadPoolExecutor can be used to set thread pool properties
method
Void execute (Runnable command): execute a task or command, which is generally used to execute Runnable
Future submit(callable task): execute a task. It is generally used to execute Callable tasks
void shutdown(): closes the thread pool
Executors: tool class and factory class of thread pool, which are used to create and return different types of threads
method
static ExecutorService newCachedThreadPool(): create a thread pool that can create new threads as needed
static ExecutorService newFixedThreadPool(n): create a thread pool with a fixed number of reusable threads
static ExecutorService newSingleThreadExecutor(): create a thread pool with only one thread
static ScheduledExecutorService newScheduledThreadPool(n): creates a thread pool that can be scheduled to run or execute periodically after a given delay
2.4. 5 Comparison of thread creation methods
Inheriting Thread class VS implementing Runnadle interface
It is more recommended to implement the Runnable interface in development. This can avoid the limitation of single class inheritance and is more suitable for data sharing among multiple threads
The Thread class actually implements the Runnable interface
3. Thread life cycle
Thread. Is used in JDK The state class defines several states of a thread
newly build
be ready
function
block
death
4. Thread synchronization
4.1 causes
When multithreading is used to share data, it will cause incomplete operation and destroy data. For an example, see testthreadbug java.
1 class TestThreaBug { 2 public static void main(String [] args) { 3 Ticket ticket = new Ticket(); 4 5 //3 Multiple threads sell tickets at the same time 6 Thread t1 = new Thead(ticket,"t1 Window ""); 7 Thread t2 = new Thead(ticket,"t2 Window "); 8 Thread t3 = new Thead(ticket,"t3 window"); 9 10 t1.start(); 11 t2.start(); 12 t3.start(); 13 } 14 } 15 16 class Ticket implements Ruunable { 17 private int tick = 20; 18 19 @Override 20 public void run() { 21 while(true) { 22 if(true > 0) { 23 System.out.println(Thred.currentThread().getName() + "Tickets sold, remaining tickets " 24 }else 25 break; 26 } 27 } 28 }
4.2 solution: synchronized
4.2. 1 synchronization code block
Limitations: when operating synchronous code, only one thread can participate and other threads wait, which is equivalent to a single threaded process with low efficiency.
synchronized(Synchronization monitor){ //The code that needs to be synchronized, that is, the code that operates the shared data }
Synchronization monitor, also known as lock. It can be an object of any class, but multiple threads must use the same lock.
Problems caused by inter thread communication
wait() method: interrupt the execution of the method and make the thread wait notify() method: wake up a thread waiting to end the wait notifyAll() method: wakes up all waiting threads to end the wait
1 package com.imooc.queue; 2 3 public class Queue { 4 private int n; 5 boolean flag = false; 6 public synchronized int get() { 7 if(!flag) { 8 try { 9 wait(); 10 } catch (InterruptedException e) { 11 // TODO Auto-generated catch block 12 e.printStackTrace(); 13 } 14 } 15 System.out.println("Consumption:"+n); 16 flag = false;//After consumption, there is no data in the container. 17 notifyAll(); 18 return n; 19 } 20 21 public synchronized void set(int n) { 22 if(flag) { 23 try { 24 wait(); 25 } catch (InterruptedException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } 29 } 30 System.out.println("Production:"+n); 31 this.n = n; 32 flag = true;//After production, there is no data in the container. 33 notifyAll(); 34 } 35 36 37 }
1 package com.imooc.queue; 2 3 public class Producer implements Runnable { 4 Queue queue; 5 Producer(Queue queue){ 6 this.queue = queue; 7 } 8 @Override 9 public void run() { 10 int i = 0; 11 while(true) { 12 queue.set(i++); 13 try { 14 Thread.sleep(1000); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 } 20 21 }
1 package com.imooc.queue; 2 3 public class Consumer implements Runnable { 4 Queue queue; 5 Consumer(Queue queue){ 6 this.queue = queue; 7 } 8 9 @Override 10 public void run() { 11 while (true) { 12 queue.get(); 13 try { 14 Thread.sleep(1000); 15 } catch (InterruptedException e) { 16 // TODO Auto-generated catch block 17 e.printStackTrace(); 18 } 19 } 20 } 21 22 23 }
1 package com.imooc.queue; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 Queue queue = new Queue(); 7 new Thread(new Producer(queue)).start(); 8 new Thread(new Consumer(queue)).start(); 9 10 } 11 12 }
1. notifyAll method is to wake up all threads. This thread cannot wake itself up. If it can wake up, it will prove that it is actually running. 2. The notify() method wakes up one thread randomly, and the notifyAll () method wakes up all threads. Because of the randomness of threads, notifyAll() is generally used 3. This case can be understood as that the producer must produce before the consumer can consume It can be controlled by an intermediate boolean variable, When flag=true, it indicates that the producer has finished production, and there is no need to carry out producer method. Execute wait() method to make the thread wait, When flag=false, it indicates that the consumer has consumed, and there is no need to perform the consumer method. Execute the wait() method to make the thread wait, Note: when the consumer method is executed, the consumer consumption is completed. At this time, the consumer thread is running and the producer thread is waiting for blocking. It is necessary to execute notifyAll method to wake up the producer thread, and vice versa.