Four, multithreading

1. Threads and processes

1.1 Threads and Processes

Process:

  • An in-memory application, where each process has a separate memory space

Thread:

  • An execution path in a process that shares a single memory space and can be switched between threads concurrently. A process must have at least one thread
  • Thread is actually a further division on the basis of the process. After a process is started, several execution paths in it can be divided into several threads

1.2 Thread Scheduling

The goal is to make better use of the CPU

Time-sharing scheduling

  • All threads take turns using the CPU, allocating equal amounts of CPU time to each thread.

Preemptive scheduling

  • Priority is given to the threads with the highest priority using the CPU. If the threads have the same priority, one is selected at random (thread randomness). Java uses preemptive scheduling.
  • The CPU uses preemptive scheduling to switch between threads at high speed. For a CPU core, only one thread can execute at a time, and the CPU switches between threads much faster than we might think, seemingly running at the same time. In fact, multi-threaded programs can not improve the speed of the program, but can improve the efficiency of the program, so that the CPU usage is higher.

2. Synchronous vs. asynchronous & concurrent vs. parallel

2.1 Synchronous and Asynchronous

Synchronization: Queue execution, inefficient but safe.

Asynchronous: Simultaneous execution is efficient but data is insecure

2.2 Concurrency and parallelism

Concurrency: Two or more events occur in the same time period.

Parallelism: Two or more events occurring at the same time (simultaneously).

3. Inherit Thread

3.1 Program Example

3.2 a sequence diagram

3.3 supplement

Each thread has its own stack space and shares a share of heap memory

4. Implement Runnable

4.1 Usage

Another way to implement multithreading

  • Create a custom class that implements the Runnable interface and override the run method.
  • Create an object r with a custom class;
  • Create an object T with the Thread class and take r as an argument to the t constructor.

4.2 Implement Runnable and Inherit Thread

1) Implementing Runnable has the following advantages over inheriting Thread

  • 1. Multi-threading is realized by creating tasks and assigning tasks to threads, which is more suitable for multiple threads to execute tasks at the same time;
  • 2. The limitations of single inheritance can be avoided (Java allows multiple interfaces, but does not allow multiple parent classes to be inherited).
  • 3, task and thread are separated, improve the robustness of the program;
  • 4. The Thread pool technology learned in the later stage accepts tasks of the Runnable type but not threads of the Thread type;

2) Thread also has certain benefits

5, the Thread class

5.1 Common construction methods

5.2 Other Common Methods

To stop a thread, declare a variable that the thread continuously monitors and calls return when the variable reaches a certain condition

All user threads are terminated before the program terminates. The daemon thread is used to guard the user thread. The user thread can be terminated automatically. After all user threads are terminated, the daemon thread will be as if there were none.

6. Set and get the thread name

7. Thread sleep

8. Interruption of threads

The outdated stop method can interrupt the thread directly, but if the thread is too late to release resources, some garbage can not be collected.

This is done by adding interrupt markers: the interrupt method is called, and the child thread catches the interrupt exception while executing. In the catch block, code is added to handle the release of the resource.

Daemon threads

9.1 an overview of the

Threads are divided into daemon threads and user threads.

  • User threads: A process terminates when it does not contain any live user threads.
  • Daemon thread: Daemon user threads. When the last user thread ends, all daemon threads die automatically.

All directly created are user threads;

SetDaemon thread: thread object. SetDaemon (true);

9.2 instance

1) Do not set the daemon thread

2) Set as a daemon thread

10, Thread safety 1- Synchronized code blocks

10.1 Causes of Thread Insecurity

Multiple threads compete for the same data, resulting in inconsistent data judgment and use. A workaround to ensure that a piece of data can only be used by one thread at a time (queued).

Solution 1: Synchronize code blocks

Format:

Synchronize (lock object){}Copy the code

10.2 Code Examples

1, unlocked

2. After locking

package com.kaikeba; import javax.xml.namespace.QName; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; import java.util.Scanner; import java.util.SimpleTimeZone; public class Demo1 { public static void main(String[] args) throws InterruptedException { Object o = new Object(); Synchronized (lock object) {// // //} Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{private int count = 10; private Object o = new Object(); @Override public void run() { //Object o = new Object(); While (true) {synchronized (o) {if (count > 0) {system.out.println (" synchronizing "); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(thread.currentThread ().getName()+" + count "); }else { break; } } } } } }Copy the code

11. Thread safety 2- Synchronization methods

The granularity of synchronous code block is fine, and a single line of code can be locked. The synchronous method, as the name implies, is to lock the method.

package com.kaikeba; import javax.xml.namespace.QName; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; import java.util.Scanner; import java.util.SimpleTimeZone; public class Demo1 { public static void main(String[] args) throws InterruptedException { Object o = new Object(); Solution 2 Synchronization Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{private int count = 10; @Override public void run() { while (true) { boolean flag = sale(); if(! flag){ break; }}} public synchronized Boolean sale(){if (count > 0) {system.out.println (" synchronized "); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(thread.currentThread ().getName()+" + count "); return true; } return false; }}}Copy the code

The lock object for this method is “this”, or “ticket.class” if it is static.

For the above code, the lock object is as follows:

12, Thread safety 3- Explicit Lock Lock

Both synchronized methods and synchronized code blocks are implicit locks, while explicit locks are manually locked and unlocked by programmers.

package thread; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; Public class Demo10 {public static void main(String[] args) {Object o = new Object(); ReentrantLock Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{private int count = 10; The default value is false. The default value is false. Private Lock l = new ReentrantLock(true); @Override public void run() { while (true) { l.lock(); If (count > 0) {// system.out.println (" count < 0 "); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(thread.currentThread ().getName()+" + count "); }else { break; } l.unlock(); }}}}Copy the code

13. Fair locks and unfair locks

13.1 the difference between

Fair lock: first come, first served, follow the queue;

Unfair locking: everyone grabs it together (synchronized code blocks, synchronized methods, and explicit locks are unfair locks);

13.2 Implementation Methods

When an explicit lock is instantiated, the argument true () is passed

14. Multithreading communication problems

This is mainly implemented with wait and notify functions

15. Producers and consumers

15.1 Prerequisites

The “cook” thread is the producer thread, the “Waiter” thread is the consumer thread, and the “food” thread is the production and consumption item.

Let’s say there’s only one cook, one waiter, and one plate. The ideal situation is: the chef produces a meal, the waiter takes away a meal, and the attributes of the meal did not occur disorder;

Chefs can prepare two flavors of food 100 times;

Waiters can take away meals 100 times;

15.2 Problem 1: The attributes of the food are abnormal

1) Experimental code

package com.kaikeba; Public class Demo1 {public static void main(String[] args) {public static void main(String[] args) {Food f = new Food(); new Cook(f).start(); new Waiter(f).start(); } static class Cook extends Thread{private Food f; public Cook(Food f) { this.f = f; } @Override public void run() { for (int i = 0; i < 100; I++) {if (I % 2 = = 0) {/ / design two vegetables color f.s etNameAndTaste (" old dopted mother millet gruel, "" sweet spicy"); }else {f.nameandtaste (" pancakes "," sweet and spicy "); }}}} // Static class Waiter extends Thread{private Food f; public Waiter(Food f) { this.f = f; } @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } f.get(); }} // static class Food{private String name; private String taste; Public void setNameAndTaste(String name,String taste){this.name = name; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.taste = taste; } public void get(){system.out.println (" +name+", "+taste +"); }}}Copy the code

2) Error phenomenon

3) The cause of the error

15.3 Problem two: Consumption/production of multiple dishes at one time

1) Experimental code

In order to prevent the time slice switch of setNameAndTaste in the production process, synchronized can be used to modify this method.

Public synchronized void setNameAndTaste(String name,String taste){this.name = name; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.taste = taste; } public synchronized void get(){system.out.println (" +name+", "+taste +"); }Copy the code

2) Operation effect

3) Cause analysis

Synchronized only ensures that thread switching will not happen inside the method, but it cannot guarantee the logical relationship of producing one and consuming one.

15.4 Solution

The cook woke up the waiter and fell asleep. The waiter after the meal wake up the cook, he fell asleep;

The main changes are setNameAndTaste and get methods:

Public synchronized void setNameAndTaste(String name,String taste){if(flag) {this.name = name; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } this.taste = taste; flag = false; This.notifyall (); Try {this.wait(); // Fall asleep} catch (InterruptedException e) {e.printstackTrace (); }}} public synchronized void get(){ Flag){system.out.println (" the name of the dish is: "+name+", the taste is: "+taste); flag = true; this.notifyAll(); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

You can see that meals are produced and consumed alternately;

16. Six states of threads

17. Callable thread with return value

New way to create threads. The previous Thread creation method: implement Thread subclass, implement Runnable interface, can be regarded as concurrent execution with the main Thread;

The thread in question is more like a task assigned by the main thread, which can get its return value;

17.1 a Runnable and Callable

1) Interface definition

//Callable Interface Public interface Callable<V> {V call() throws Exception; } //Runnable public interface Runnable {public void run(); }Copy the code

2) Similarities

All is the interface

Can write multithreaded programs

Both start threads with thread.start ()

3) Differences

Runnable has no return value; Callable can return execution results

The Call () of the Callable interface allows exceptions to be thrown; Runnable run() cannot be thrown

17.2 Procedure for using Callable

1. Write classes to implement Callable interface and call method

class XXX implements Callable<T> { @Override public <T> call() throws Exception { return T; }}Copy the code

2. Create a FutureTask object and pass in the Callable class object you wrote in the first step

FutureTask<Integer> future = new FutureTask<>(callable); 
Copy the code

3. Start the Thread through Thread

new Thread(future).start();
Copy the code

17.3 Common Methods

1) Method introduction

2) Code examples

package com.kaikeba; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class Demo1 { public static void main(String[] args) { Callable<Integer> c = new MyCallable(); FutureTask<Integer> f = new FutureTask<>(c); new Thread(f).start(); for(int i = 0; i < 10; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + i); } } static class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { // Thread.sleep(100); For (int I = 0; i < 10; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + i); } return 100; }}}Copy the code

When the GET method is not used, the main thread executes alternately with another thread

Use the get method

18. Thread pool Overview

18.1 Why is a thread pool needed

If there are a large number of concurrent threads, and each thread executes a short task and then terminates, creating threads frequently can greatly reduce the efficiency of the system because of the time it takes to create and destroy threads frequently.

A thread pool is a container that holds multiple threads. Threads in the pool can be used repeatedly, eliminating the need to create thread objects frequently and saving a lot of time and resources.

Four thread pools in Java (all ExecutorService objects)

18.2 Caching thread pools

1) overview

/*** Cache thread pool. * (length unlimited) * execution process: * 1. Whether the thread pool is the idle thread * 2. There is use * 3. Doesn't exist, create a thread And in the thread pool, and then use the * / ExecutorService service = Executors. NewCachedThreadPool (); Execute (new Runnable() {@override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }}); service.execute(new Runnable() { @Override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }}); service.execute(new Runnable() { @Override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }});Copy the code

2) Code examples

package com.kaikeba; import java.util.concurrent.*; public class Demo1 { public static void main(String[] args) throws ExecutionException, InterruptedException {/*** The cache thread pool. * (unlimited length) * The execution process: * 1. Whether the thread pool is the idle thread * 2. There is use * 3. Doesn't exist, create a thread And in the thread pool, and then use the * / ExecutorService service = Executors. NewCachedThreadPool (); Execute (new Runnable() {Override public void run() { System.out.println(thread.currentThread ().getName() + "thread.currentThread () "); }}); Service. Execute (new Runnable() {// Public void run() { System.out.println(thread.currentThread ().getName() + "thread.currentThread () "); }}); Service. Execute (new Runnable() {// Public void run() { System.out.println(thread.currentThread ().getName() + "thread.currentThread () "); }}); }}Copy the code

After sleeping for a while, add a new task to see if you can take advantage of existing threads in the thread pool:

18.3 Fixed-length thread pool

1) overview

/** * fixed length thread pool. * (length is specified number) * execution flow: * 1. If there are no free threads and the thread pool is full, create a thread and add it to the thread pool. Then use * 4. There is no idle thread and thread pool is full of cases, the waiting thread pool is the idle thread * / ExecutorService service = Executors. NewFixedThreadPool (2); service.execute(new Runnable() { @Override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }}); service.execute(new Runnable() { @Override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }});Copy the code

2) Code examples

Set the thread pool size to 2, that is, a maximum of two threads can exist in the thread pool.

The first two threads execute and sleep for three seconds;

The third task cannot create new threads because the thread pool is full, so it must wait for free threads to appear in the thread pool before it can execute.

package com.kaikeba; import java.util.concurrent.*; Public class Demo1 {/* The thread pool length is the execution process after the specified thread pool is added to the task. 1 Check whether there are free threads in the thread pool. 2 If there are no free threads and the thread pool is full, create a thread and add it to the thread pool **/ public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(2); service.execute(new Runnable() { @Override public void run() { System.out.println(thread.currentThread ().getName()+" "); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }}}); service.execute(new Runnable() { @Override public void run() { System.out.println(thread.currentThread ().getName()+" "); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }}}); service.execute(new Runnable() { @Override public void run() { System.out.println(thread.currentThread ().getName()+" "); }}); }}Copy the code

18.4 Single-threaded thread pool

1) overview

/** * single thread pool. Check whether the thread in the thread pool is free * 2. Not free, then wait for a single thread in the pool is used after free * / ExecutorService service = Executors. NewSingleThreadExecutor (); service.execute(new Runnable() { @Override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }}); service.execute(new Runnable() { @Override public void run() { Println (" Thread name :"+ thread.currentThread ().getName()); }});Copy the code

2) Code examples

package com.kaikeba; import java.util.concurrent.*; Public static void main(String[] args) {public static void main(String[] args) {public static void main(String[] args) {  ExecutorService service = Executors.newSingleThreadExecutor(); service.execute(new Runnable() { @Override public void run() { System.out.println(thread.currentThread ().getName()+" "); }}); service.execute(new Runnable() { @Override public void run() { System.out.println(thread.currentThread ().getName()+" "); }}); service.execute(new Runnable() { @Override public void run() { System.out.println(thread.currentThread ().getName()+" "); }}); }}Copy the code

18.5 Periodic thread pool with fixed length

1) overview

Public static void main(String[] args) {/** * Specifies the thread pool for periodic tasks. If there are no free threads and the thread pool is full, create a thread and add it to the thread pool. Then use * 4. If there are no free threads and the thread pool is full, wait for the thread pool to have free threads * * periodic task execution: * perform regularly, when a certain time to trigger, automatically perform a certain task. * / ScheduledExecutorService service = Executors. NewScheduledThreadPool (2); /** * Scheduled execution of * parameter 1. Runnable task * parameter 2. */ /* Service. Schedule (new Runnable() {@override public void run() {system.out.println ( Gnome male - ", "); } },5,TimeUnit.SECONDS); */ /** * Periodic execution * Parameter 1. Runnable task * parameter 2. Duration number (latency for execution) * Parameter 3. Cycle duration (interval for each execution) * Parameter 4. Length of digital unit * / service. The scheduleAtFixedRate (new Runnable () {@ Override public void the run () {System. Out. Println (" two people each other a smile ~ gnome male - "");  }}, 5, 2, TimeUnit. SECONDS); }Copy the code

2) Code examples

package com.kaikeba; import java.util.concurrent.*; Public class Demo1 {/* Periodic task Fixed length thread pool execution flow 1 Check whether there are free threads in the thread pool. 2 Check whether there are free threads in the thread pool. If there are no free threads and the thread pool is full, use 3 **/ public static void main(String[] args) {public static void main(String[] args) { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2); // Scheduled execution // Parameter 1: scheduled execution // Parameter 2: duration number // Parameter 3: 2 units of time Timeunit constants to specify / * scheduledExecutorService. The schedule (new Runnable () {@ Override public void the run () { System.out.println(thread.currentThread ().getName()+" "); } },5, TimeUnit.SECONDS); //5 seconds later */ /* Periodically execute a task parameter 1: task parameter 2: delay period number (delay time of the first execution) Parameter 3: Period period number (how often to execute a task) Parameter 4: The length unit number * * * / scheduledExecutorService. ScheduleAtFixedRate (new Runnable () {@ Override public void the run () { System.out.println(thread.currentThread ().getName()+" "); }}, 5, 1, TimeUnit. SECONDS); }}Copy the code

Lambda expression

19.1 Why lambda expressions

For some application scenarios, we focus more on the result, if we can solve it with a method, then creating objects and calling methods may be more tedious;

1) Redundant Runnable methods

Public class Demo1 {/** * lambda expressions * Functional programming ideas (result-oriented, object oriented by creating objects, @param args */ public static void main(String[] args) {Runnable r = new MyRunnable(); Thread t = new Thread(r); t.start(); Static class MyRunnable implements Runnable{@override public void run() {static class MyRunnable implements Runnable{@override public void run() { System.out.println(" Mission completed! ") ); }}}Copy the code

2) Simplify code with anonymous inner classes

Public class Demo1 {/** * lambda expressions * Functional programming ideas (result-oriented, object oriented by creating objects, @param args */ public static void main(String[] args) {Thread t = new Thread(new Runnable() { @override public void run() {system.out.println (" Job done! ); }}); t.start(); // Write so much to complete a simple task}}Copy the code

19.2 Example

1) Don’t use lambda

package com.kaikeba; import java.util.concurrent.*; Public class Demo1 {/** * lambda expressions * Functional programming ideas (result-oriented, object oriented by creating objects, Public static void main(String[] args) {print(new MyMath() {@override public int sum(int x, int y) { return x + y; }}, 100, 200); } public static void print(MyMath m, int x, int y){ int num = m.sum(x, y); System.out.println(num); } static interface MyMath{ int sum(int x, int y); }}Copy the code

2) Use lambda

You don’t need to implement interfaces and instantiate objects;

package com.kaikeba; import java.util.concurrent.*; Public class Demo1 {/** * lambda expressions * Functional programming ideas (result-oriented, object oriented by creating objects, Public static void main(String[] args) {print((int x, int y) -> {return x + y; }, 100, 200); } public static void print(MyMath m, int x, int y){ int num = m.sum(x, y); System.out.println(num); } static interface MyMath{ int sum(int x, int y); }}Copy the code