The introduction

As computers become more and more highly configured, we need to further optimize the process, subdivided into threads, fully improve the development of multithreading graphical interfaces. This requires a thorough understanding of threads. So without further ado, today Ben shuai will record his own thread learning.

Basic concepts of programs, processes, and threads + parallelism and concurrency:

Program: A set of instructions written in a language to accomplish a specific task, i.e. a static piece of code, a static object. Process: an execution of a program, or a running program, is a dynamic process, with its own generation, existence and death. ——- Lifecycle thread: A process can be further refined into a thread, which is an execution path within a program

Thread (a program can have more than one thread) program: static code process: dynamically executing program Thread: When several things need to be done simultaneously in a process, the execution path of each thing becomes a thread.

Parallelism: Multiple cpus performing multiple tasks at the same time, for example: multiple people doing different things at the same time. Concurrency: one CPU (using a time slice) performing multiple tasks at the same time, such as a seckill platform, where multiple people are doing the same thing

Thread apis

Thread.currentthread ().getName()

1. Start ():1. Start the currentThread 2. Call the run method in the Thread 2. GetName (): gets the name of the current thread 5.setName(): sets the name of the current thread 6.yield(): actively releases the execution of the current thread 7.join(): inserts the execution of another thread in the thread that is blocked, 8. Stop (): Obsolete method. When this method is executed, the current thread is forced to terminate. 9. Sleep (long millitime) : the thread sleeps for a period of time 10. IsAlive () : checks whether the current thread isAlive

Check whether it is multithreaded

A thread is an execution path, i.e. a thread when drawn with a path: the following appears to execute method 1 and method 2, but the main thread is executing method 2 and method 1, so it is a thread

Public class Sample{public void method1 (String STR) {system.out.println (STR); } public void method2(String str){ method1(str); } public static void main(String[] args){ Sample s = new Sample(); s.method2("hello"); }}Copy the code

Scheduling of threads

Scheduling policy: Time slice: Threads are scheduled in a time slice rotation mode. Preemption: Threads with higher priorities preempt CPUS. Java scheduling method: 1. For threads of the same priority to form a first-in, first-out queue (first-come, first-served), time slice policy 2 is used. For high priorities, preemptive scheduling is used

Priority of the thread

Level: MAX_PRIORITY:10 MIN_PRIORITY:1 NORM_PRIORITY:5

SetPriority (int newPriority): changes the priority of the thread

Attention! : a higher priority thread preempts the CPU execution of a lower priority thread. But on a probabilistic basis, threads with higher priority are more likely to be executed. This does not mean that low-priority threads execute only after high-priority threads finish executing.

Multithreaded way to create

1. Method 1: Inherit from Thread

1. Create a subclass that integrates with Thread (search for the run method by pressing CTRL + O (override)) 2. Overrides the run () method of Thread class 3. Creates object 4 of Thread subclass. Call the start () method from this object

The difference between the start and run methods:

Learn about Java multithreading at once:

www.cx1314.cn/thread-3531…

The start method does: 1. Start the current thread 2. Call the current thread’s rewriting of the run method (child thread is generated in the main thread, there are two threads) to invoke the start method, a path on behalf of a single thread, thread two execution at the same time, because of the time slice rotation, so the execution process of random distribution, and a thread object can only be called once start method. The run method is used to execute the run method in the main thread. (Call the run method in the thread, only call the run method, do not open a new thread)

Conclusion: We can’t run method to open a new thread, can only be rewritten in the calling thread’s run method (can constantly invoke the run method in the thread, but can’t open the child thread, or can’t do several things at the same time, the start was to start a thread, and then calls the method (i.e. the default open a thread to call a run method, can perform several things at the same time)

Multithreading example (train station multi-window ticket selling problem)

package com.example.paoduantui.Thread; import android.view.Window; /** ** create three Windows to sell tickets, a total of 100 tickets, using the inheritance of Thread mode * use static variables to ensure that three threads of data is a single copy ** there are Thread security issues, * * */ public class ThreadDemo extends Thread{public static void main(String[] args){window t1 = new window(); window t2 = new window(); window t3 = new window(); T1.setname (" ticket 1"); T2.setname (" ticket 2"); T3.setname (" 表 3"); t1.start(); t2.start(); t3.start(); } } class window extends Thread{ private static int ticket = 100; @override public void run() {while(true){if(ticket>0){// try {// sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); / /} System. Out. Println (getName () + "currently sold in the first" + ticket + "ticket"); ticket--; }else{ break; }}}}Copy the code

2. Mode 2: Implement the Runable interface mode

Create a class that implements the Runable interface. 2. Implement the abstract Runnable method: run() 3. Create an object of the implementation class. 4. Pass this object as a parameter to the constructor of Thread, creating an object of Thread 5. Call start () from an object of the Thread class

To do this, a class implements the Runable interface (plug in the interface). On the other side, objects through the implementation class and thread objects are implemented through the Runable interface plug interface

package com.example.paoduantui.Thread; public class ThreadDemo01 { public static void main(String[] args){ window1 w = new window1(); T1 =new Thread(w); t1=new Thread(w); t1=new Thread(w); Thread t2=new Thread(w); Thread t3=new Thread(w); T1. Elegantly-named setName (" window 1 "); T2. Elegantly-named setName (" window 2 "); 3 t3. Elegantly-named setName (" window "); t1.start(); t2.start(); t3.start(); } } class window1 implements Runnable{ private int ticket = 100; @Override public void run() { while(true){ if(ticket>0){ // try { // sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); //} system.out.println (thread.currentThread ().getName()+" "+ticket+"); ticket--; }else{ break; }}}}Copy the code

Cause 1: The implementation method does not have the limitations of single inheritance of classes. 2: The implementation method is more suitable for handling situations where multiple threads have shared data: Thread is also implemented from Runable, and either way you override the run () method to declare the logic to be executed by the Thread in run

3. Two new ways to create multiple threads

1. Implement callable interface mode:

Callable is more powerful than runnable: The run method overridden by Runnable is not as powerful as Callaalbe’s Call method, which can have a return value and can throw an exception. Generics-supported return values need the help of the FutureTask class, such as retrieving the return result

package com.example.paoduantui.Thread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Thread creation method 3: implement callable interface. --JDK 5.0 new * whether multithreading? No, only one thread * * has one more FutureTask class than Runable, which receives the return value of the Call method. * Applies to the form that needs to receive a return value from a thread * * // Callable implements the steps of creating a new thread: * 1. Create an implementation class that implements callable * 2. Implement the Call method and declare the operations this thread needs to perform in Call () * 3. Create an object for the Callable implementation class * 4. Create an object for FutureTask * 5 by passing the object for the Callable interface implementation class to the constructor of FutureTask. Pass the FutureTask object as a parameter to the Thread constructor to create the Thread object, * * */ / Implement the call method class NumThread implements callable {// implement the call method class NumThread implements callable { private int sum=0; // // can throw an Exception @override public Object call() throws Exception {for(int I = 0; i<=100; i++){ if(i % 2 == 0){ System.out.println(Thread.currentThread().getName()+":"+i); sum += i; } } return sum; }} public class ThreadNew {public static void main(String[] args){NumThread NumThread = new NumThread(); FutureTask futureTask = new futureTask (numThread); Thread t1 = new Thread(futureTask); T1. Elegantly-named setName (" thread 1 "); t1.start(); Object sum = futureTask.get(); // Get = futureTask.get(); System.out.println(Thread.currentThread().getName()+":"+sum); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code
How to use thread pools:

Background: Frequently created and destroyed, very heavy resources, such as threads in concurrent cases, have a significant impact on performance. Create several threads in advance, put them into the thread pool, get them directly when used, put them back into the pool. It can avoid frequent creation and destruction and realize reuse. Similar to public transportation in life. (Database connection pool) Benefits: Increased response time (reduced time to create new threads) reduced resource consumption (reuse of threads in the thread pool, not need to be created every time) easy thread management corePoolSize: maximumPoolSize: keepAliveTime: What is the maximum amount of time a thread can hold without a task before terminating…

JDK 5.0 provides the thread pool API: ExecutorService and ExecorService: True thread pool interface. Void execute(Runnable coommand): executes a task/command. Runnable Futuresubmit(Callable task): executes a task. Callable void shutdown () : closes the connection pool.

Executors

The utility class, a factory class for thread pools, is used to create and return different types of thread pools

Executors.newCachedThreadPool()

Create a thread pool that can create new threads as needed

Executors.newFixedThreadPool(n)

Create a reusable thread pool with a fixed number of threads

Executors.newSingleThreadExecutor()

: Creates a thread pool with only one thread

Executors.newScheduledThreadPool(n)

Create a thread pool that can schedule commands to run after a given delay or to execute them periodically.

Thread pool constructs bulk thread code as follows:

package com.example.paoduantui.Thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Create thread 4: use thread pool *1. You need to create objects that implement the Runnable or Callable interface * 2. Create an ExecutorService thread pool * 3. Place the created objects that implement the Runnable interface class into the Execute method of the ExecutorService object. * * */ class NumberThread implements Runnable{@override public void run() {for(int I = 0; i<=100; i++){ if (i % 2 ==0 ) System.out.println(Thread.currentThread().getName()+":"+i); } } } class NumberThread1 implements Runnable{ @Override public void run() { for(int i = 0; i<100; i++){ if(i%2==1){ System.out.println(Thread.currentThread().getName()+":"+i); }}}} public class ThreadPool {public static void main(String[] args){// create a ThreadPool with ten fixed threads executorService = Executors.newFixedThreadPool(10); // New a Runnable interface object NumberThread Number = new NumberThread(); NumberThread1 number1 = new NumberThread1(); Executorservice. execute(number1); executorService.execute(number); Executorservice.submit (); //executorService.submit(); Executorservice.shutdown (); // ExecutorService.shutdown (); }}Copy the code

To call a new Thread, both methods now require the start method in Thread.

Java Virtual Machine (JVM) : Java Virtual Machine memory structure

Program (a static piece of code) —————— “loaded into memory ——————” process (loaded into memory code, dynamic program)

Processes can be subdivided into threads, with one thread representing a path of execution within a program

Each thread has its own separate program counter (PC, which guides the program down) and run stack (local variables, local methods, etc.)

Thread communication method:

Wait ()/ notify()/ notifayAll(): These three methods are defined in the Object class. They are defined in the Object class because they require locks, which can be used by any Object.

Because wait, notify, and notifyAll all involve the lock-related operation wait (to block and wait after entering the locked area, —- Obj. Wait Threads that enter Obj’s locked area hand over the lock and wait for notify. —– obj.notify The new thread enters the Obj area to operate and wake up the wait thread

It is similar to when I want to poop. I go to the toilet and close the door, but there is a sign saying that the toilet can not be used, so I lock the toilet to someone else. I don’t know who comes in to poop or fix the toilet until someone tells me that the toilet is ready.

In order to ensure that the wait and notify regions are the same locked region, they need to be identified by the same object as the lock

Classification of threads:

Threads in Java fall into two categories: 1. Daemon threads (garbage collection threads, exception handling threads) and 2. User threads (such as the main thread)

If the JVM is full of daemons, the current JVM exits. (Image understanding, when lips are gone, teeth are cold)

Thread life cycle:

The JDK uses the thread. State class to define several Thread states, as follows:

Phase of the thread life cycle

describe

new

When an object of the Thread class or its subclass is declared and created, the newly created Thread object is in the new state

ready

After the thread is started, it will enter the thread queue to wait for the CPU time slice. At this time, it is ready to run, but no CPU resources are allocated

run

When a ready thread is scheduled and CPU resources are acquired, the run method defines the actions and functions of the thread

blocking

In some special cases, when the input/output operation is suspended or executed artificially, the CPU is relinquish and its execution is temporarily terminated, and the state is blocked

death

The thread completes all of its work or the thread is forced to terminate prematurely or an exception occurs resulting in termination

Thread synchronization: Only one thread can exist in a synchronized code block.

Thread safety issues:

What are thread safety issues? Thread safety refers to that when multiple threads operate on the same shared data, the thread does not have time to update the shared data. As a result, other threads do not get the latest data, resulting in thread safety problems.

In the above example: create three Windows to sell tickets, and the total number of tickets is 100. 1. In the process of selling tickets, duplicate tickets appeared (tickets were sold repeatedly and tickets were printed out if they were not reduced). 2. The cause of the problem: when a thread is operating the ticket, but the operation has not been completed, other threads join in and also operate the ticket. (Think of the code for this process as an area, when a thread enters, lock it, and prevent other threads from entering.) Example of vivid understanding: there is a toilet, someone enters, but it is not locked, so others do not know that you enter, others also enter the toilet to use the error. 3. How to solve this problem: When a thread performs ticket operations, other threads cannot participate until the end of the thread’s life cycle. In Java, we address thread safety through synchronization.

Synchronized {// Code that needs to be Synchronized}

  1. Code that operates on shared data (code that operates on data shared by all threads) (viewed as a bathroom area (toilet shared by all)) is code that needs to be shared (synchronized code blocks, in synchronized code blocks, are equivalent to a single thread, inefficient)
  2. Shared data: Data that is operated by multiple threads, such as a public toilet, is analogous to shared data
  3. Synchronization monitor (commonly known as lock) : Any object can act as a lock. When locked, only one thread can enter (requirement: multiple threads must share the same lock, such as the toilet on a train, the same sign indicates that there are people).

Runable naturally shares locks, while Thread requires static objects or the this keyword or the current class (window). Class) to act as a unique lock

Method 2: Synchronized Method: Use a synchronized method to modify the method with the synchronized keyword. Extract the synchronized code block as a method, and modify the method with the synchronized keyword. For the runnable interface to implement multithreading, you only need to use the synchronized method modifier. For inheriting from Thread, you need to use the static and synchronized methods modifier, because objects are not unique.

Summary: 1. The synchronization method still involves the synchronization monitor, but does not require the declaration we display. 2. Non-static synchronization methods, the synchronization monitor is the this static synchronization method, the synchronization monitor is the current class itself. Inheriting from Thread. class

Method 3: LOCK method in JDK5.0

package com.example.paoduantui.Thread; import java.util.concurrent.locks.ReentrantLock; class Window implements Runnable{ private int ticket = 100; Private ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true) { //2. Call the lock method lock lock.lock(); if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (thread.currentThread ().getName()); ticket--; } else { break; } } } } public class LockTest { public static void main(String[] args){ Window w= new Window(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); T1. Elegantly-named setName (" window 1 "); T2. Elegantly-named setName (" window 1 "); T3. Elegantly-named setName (" window 1 "); t1.start(); t2.start(); t3.start(); }}Copy the code

Summary: Similarities and differences between Synchronized and lock?

Identical: Both can solve thread safety problems different: Synchronized releases the monitor lock manually (lock ()) and ends it manually (unlock ()) after executing the code logic.

Priority order: LOCK- “synchronization code block -” synchronization method

Determine if there is a thread security problem and how to resolve it:

Check whether there are multiple threads. 2. Check whether shared data exists. 3. Choose the three methods above to solve the thread safety problem

Examples:

package com.example.paoduantui.Thread; /*** * Description: Both party A and Party B deposit money in the bank at the same time, saving up to 3000 *** */ // Public Account(double balance) {this.balance = balance; } public synchronized void deposit(double amt){if(amt>0){balance +=amt; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println (thread.currentThread ().getName()+" +balance "); Class Customer extends Thread{private Account acct; public Customer(Account acct){ this.acct = acct; } @Override public void run() { for (int i = 0; i<3; i++){ acct.deposit(1000); }}} // the main method, where the same account, a and b two savings thread. public class AccountTest { public static void main(String[] args){ Account acct = new Account(0); Customer c1 = new Customer(acct); Customer c2 = new Customer(acct); C1. Elegantly-named setName (" a "); C2. Elegantly-named setName (" b "); c1.start(); c2.start(); }}Copy the code

Solve the lazy thread-safety problem of singletons:

Singleton: Only one instance can be obtained through a static method. Instance 1 cannot be constructed through a constructor. Private static Bank instance = null; private static Bank instance = null; // Initialize the static instance

Public static Bank getInstance () {if (instance! =null) {instance = new Bank(); } return instance; }

If multiple threads call this singleton, and the function called to get the singleton as an operation to share the code block of the singleton does not solve the thread safety problem, it will lead to multiple threads to determine whether the instance is empty, this will lead to the generation of multiple instances, that is, the thread-safety problem of the singleton pattern.

Thread safety:

  1. Rewrite the method of obtaining singletons as the same part of the method, that is, add the synchronized keyword, at this time the synchronization monitor is the current class itself. (When multiple threads concurrently acquire instances, only one thread can acquire instances at a time), which solves the thread-safety problem of singleton mode.
  2. The way synchronization blocks are wrapped around synchronization monitors.

The lazy singleton model, for example: The life of limited edition buying: When a group of people of concurrent rob a limited edition, things may be grabbed a few people at the same time, they went into the room at the same time (within the synchronized code block) but only the first to get the limited edition of things people can come to hand, other people can’t get, so efficiency is a little higher, when something is taken, we set up a sign at the door, sold out. This reduces the wait of the thread. Which is the slightly more efficient lazy way of writing:

package com.example.paoduantui.Thread; Public class Bank {// private Bank constructor private Bank(){} private static Bank instance = null; Public static Bank getInstance(){if(instance==null){instance= new Bank(); if(instance==null){instance= new Bank(); } return instance; } public static synchronized Bank getInstance1(){if(instance==null){instance= new Bank(); } return instance; } public static Bank getInstance2(){synchronized (bank.class){if(instance==null){instance= new Bank(); } return instance; }} / / efficient thread-safe LanHanShi singleton pattern / * * * because when high concurrent calls the singleton pattern is similar to the ten thousand people in indiana, the only people who enter the room first get treasure, * when more than one person to enter the room, the first man took away the treasures, also a few other people have to wait outside the synchronized code block, * The rest only need to see the "sold out" sign at the door, i.e. the treasure is known to have been taken, so they don't need to enter the synchronized code block, which improves efficiency. * * * */ public static Bank getInstance3(){ if (instance==null){ synchronized (Bank.class){ if(instance==null){ instance  = new Bank(); } } } return instance; }}Copy the code
  • 52
  • 53

Thread deadlocks:

Deadlock: deadlock, no one will let go, a pair of chopsticks, each one of you, wait for the other party to let go

package com.example.paoduantui.Thread; Public class Demo {public static void main(String[] args){final StringBuffer s1 = new StringBuffer(); final StringBuffer s2 = new StringBuffer(); New Thread(){@override public void run() {// synchronized (s1){s1.append("a"); s2.append("1"); synchronized (s2) { s1.append("b"); s2.append("2"); System.out.println(s1); System.out.println(s2); } } } }.start(); New Thread(new runnable () {@override public void run() {synchronized (s2){synchronized (s2){ s1.append("c"); s2.append("3"); synchronized (s1) { s1.append("d"); s2.append("4"); System.out.println(s1); System.out.println(s2); } } } }).start(); }}Copy the code

Running results:

1. Call the above thread first, then call the following thread:



2. Deadlocks occur:



3. Call the following thread first and then the above thread.

Deadlock solutions:

1. Reduce the synchronization of shared variables. 2. Reduce lock nesting.

Thread communication

Common communication methods:

Communication method

describe

wait()

Once this method is executed, the current thread blocks and releases the synchronization monitor

notify

Once this method is executed, one of the threads being waited is woken up, or if there are multiple threads, the one with the highest priority is woken up

notifyAll

Once this method is executed, all threads being waited () are awakened

Prerequisites: All three methods can only be used in synchronized code blocks or synchronized methods.

package com.example.paoduantui.Thread; /** * An example of thread communication: use two threads to print 1-100, thread 1, thread 2 alternately ** When we do not take communication between threads, we cannot achieve thread 1, 2 interprint (CPU control is automatically assigned) * To achieve thread 1, 2 interprint, we need: * 1. After thread 1 acquires the lock, go into the code block and add number++ (number print and increment), to ensure that the next lock is owned by thread 2, thread 1 needs to block (thread 1 you wait ()). (output 1, number = 2) * 2. After thread 2 has acquired the lock, thread 1 cannot enter the synchronization block. Therefore, in order for thread 1 to preempt the next lock, thread 1 needs to cancel the blocking state (notify () and notifyAll ()). That is, thread 1 should be unblocked when entering the synchronized code block. * * */ class Number implements Runnable{ private int number = 1; // Set the shared data (shared data between threads is communication) // the code block that operates on the shared data, @override public synchronized void run() {while(true){notify(); If (number<100){try {thread.sleep (10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+number); number++; try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }else{ break; }}}} public class CommunicationTest {public static void main(String[] args){// Create runnable object Number Number = new Number(); Thread t1 = new Thread(number); Thread t2 = new Thread(number); // Set the thread name to t1.setName(" thread 1"); T2. Elegantly-named setName (" thread 2 "); // Start thread t1.start(); t2.start(); }}Copy the code

Similarities and differences between sleep and wait:

Similarities: Once the method is executed, the current process will be blocked. Point: 1. The methods declare sleep in Thread and wait in Object. 2. Call requirements vary. Sleep can be invoked in any scenario where it is needed, and wait must be used in synchronized code blocks or synchronized methods. In terms of whether to release the synchronization monitor, if both methods are used in synchronized code blocks or synchronized methods, sleep is not released and wait is released

Producer/consumer problem:

The Priductor gives the product to the Clerk, who takes it from the Customer. The Clerk can only hold a fixed number of products at a time (say 20). If the producer view produces more products, the Clerk will ask the producer to stop. Notify the producer to continue production if there is room for the product: If there is no product in the store, the clerk will tell the consumer to wait, and notify the consumer to pick up the product if there is a product in the store.

There are two possible problems here: when producers are faster than consumers, consumers miss some data and do not receive it. When the consumer is faster than the producer, the consumer will go to the same data.

package com.example.paoduantui.Thread; /** * Thread communication applications: producer/consumer issues ** 1. Is it a multithreading problem? Yes, there are producer threads and consumer threads (multithreaded creation, four ways) * 2. Is there a shared data problem with multithreading? There are shared data ---- products (synchronization method, synchronization code block, lock lock) * 3. Does multithreading have thread safety issues? All operations on shared data products exist at ----. (3 methods) * 4. Whether there is communication between threads, yes, if the production is 20 more than the need to notify to stop production (wait). * * */ class Clerk{private int productCount = 0; Public synchronized void produceProduct() {if(productCount<20) {productCount++; System.out.println(thread.currentThread ().getName()+": productCount+"); notify(); }else{// Wait try {wait(); } catch (InterruptedException e) { e.printStackTrace(); Public synchronized void consumeProduct() {if (productCount>0){ System.out.println(thread.currentThread ().getName()+": productCount+"); productCount--; notify(); }else{// wait for try {wait() when 0; } catch (InterruptedException e) { e.printStackTrace(); }}}} class Producer extends Thread{// Producer Thread private Clerk Clerk; public Producer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"; Start producing products......" ); while(true){ clerk.produceProduct(); }} class Consumer implements Runnable{// Consumer implements Runnable; public Consumer(Clerk clerk) { this.clerk = clerk; } @override public void run() {system.out.println (thread.currentThread ().getName()+": "); while(true){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } clerk.consumeProduct(); } } } public class ProductTest { public static void main(String[] args){ Clerk clerk = new Clerk(); Producer p1 = new Producer(clerk); P1.setname (" producer 1"); Consumer c1 = new Consumer(clerk); Thread t1 = new Thread(c1); T1.setname (" consumer 1"); p1.start(); t1.start(); }}Copy the code