Java learning day022-025 (multithreading - Lecture Notes version)

Posted by SiriusB on Tue, 21 Dec 2021 19:53:34 +0100

Write in front: I haven't studied very seriously these two days. This article is sorted out according to the dark horse video on station b. There are still many imperfections. I'll look at the teacher's video screen for detailed sorting after a while

8.13. I started to write notes again and watched the video twice. It's really good

1. How does Java implement multitasking

java is multithreaded to achieve multitasking!!!
There is no multi process and co process programming in java!!!!

2.java multithreading programming

|-- inherit Thread class
|-- realization Runable Interface
|-- Callable and Future Interface( jdk1.5)
|-- Thread pool( jdk1.5)

3. Inherit Thread class method 1: inherit Thread class

  • Define a class MyThread to inherit the Thread class
  • Override the run() method in the MyThread class
  • Create an object of the MyThread class
  • Start thread

Two small problems:

  • Why override the run() method?
    • Because run() is used to encapsulate the code executed by the thread
  • What is the difference between the run() method and the start() method?
    • run(): encapsulates the code executed by the thread. It is called directly, which is equivalent to the call of ordinary methods
    • start(): start the thread; The run() method of this thread is then called by the JVM
package com.study_01;

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
package com.study_01;

public class MyThreadDemo {
    public static void main(String[] args) {
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();

//        my1.run();
//        my2.run();

        // void start() causes this thread to start execution; The Java virtual machine calls the run method of this thread.
        my1.start();
        my2.start();
    }
}

4. Implement the interface of Runable

Method 2: implement Runnable interface

  • Define a class MyRunnable to implement the Runnable interface
  • Override the run() method in the MyRunnable class
  • Create an object of the MyRunnable class
  • Create an object of Thread class and take the MyRunnable object as the parameter of the construction method
  • Start thread

There are two implementation schemes of multithreading

  • Inherit Thread class
  • Implement Runnable interface

Advantages of implementing the Runnable interface over inheriting the Thread class

  • It avoids the limitation of Java single inheritance
  • It is suitable for multiple codes of the same program to deal with the same resource, and effectively separates the thread from the program code and data, which better reflects the object-oriented design idea
package com.study_05;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
package com.study_05;

public class MyRunnableDemo {
    public static void main(String[] args) {
        // Create an object of the MyRunnable class
        MyRunnable my = new MyRunnable();

        // Create an object of Thread class and take the MyRunnable object as the parameter of the construction method
        // Thread(Runnable target) assigns a new thread object.
//        Thread t1 = new Thread(my);
//        Thread t2 = new Thread(my);

        // Thread(Runnable target, String name)
        Thread t1 = new Thread(my,"high-speed rail");
        Thread t2 = new Thread(my,"aircraft");

        //Start thread
        t1.start();
        t2.start();

    }
}

5.Callable and Future interfaces (jdk1.5)

The juc package is 5.0
Callable and Future interfaces

The Callable interface needs a generic type, which refers to the type of result to be returned after the thread method is executed;

TaskFuture implementation class in the Future interface
This implementation class has implemented the Future and Runable interfaces

package com.study.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class TestThread03 {
    public static void main(String[] args) {
        // Create a Callable thread object
        MyThread03 mt = new MyThread03();
        // FutureTask object
        FutureTask<String> future = new FutureTask<String>(mt);

        // The current thread was started
        new Thread(future, "call_thread").start();

        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() +"The main thread is running"+ i);
        }

        // Note: use the get method to get the return value after the thread runs
        // This method is called after all threads are started
        try {
            System.out.println("After the child thread runs, the result is:" + future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class  MyThread03 implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
        return "The return value after the thread runs";
    }
}

6. Some common methods of Thread objects

Some common methods of Thread objects:

start()			# Start thread
run()			# This method cannot be manually executed. It is a thread method. It is executed by the start method. The JVM bottom layer automatically executes this method
setName(name)		# Set thread name
getName()		# Get thread name
getId()			# Get thread number
getPriority()		# Gets the priority of the thread
interrupt();
isAlive()		# Determine whether the thread is alive
isDaemon()		# Determine whether the thread is a daemon thread
setDaemon(true);	# Set the current thread as a daemon
join();			# Block the main thread and let the sub thread run after it is completed

Thread.sleep(millisecond)	# Static method. If the current thread sleeps, whether to lock it or not
Thread.yield()		# Letting the current thread give up once will not release the lock

seven ✨ What is the difference between inheriting Thread and implementing Runable interface?

inherit Thread Class, multiple thread objects cannot share member variables!!!
	If it is a static member, it is also shared!!!!

realization Runable Interfaces are sub thread classes, and multiple thread objects share the member variables of thread classes!!!

8. Synchronous lock

There are three ways to write
1,Put it on the method: the whole method is synchronous
	If all code in a method may have thread safety problems, it is recommended to synchronized
	Write directly on the method if synchronized Write it on the method, which is the lock

2,Synchronization block: put the code that may be thread safe in a synchronization block
	key It is an object. Any object can be used. It is generally recommended to use it this Keywords act as
	   synchronized (key) {
		// Thread safety issues may occur
		count++;
	    }

3,Static method: it's special. Let's say it alone
	The static method adds synchronized Keyword, because the static method belongs to a class, the class (essentially the bytecode file of the class) acts as a lock.

Class content starts on August 9

👀date8.9—

9.Lock lock

Although we can understand the lock object problem of synchronization code blocks and synchronization methods, we do not directly see where the lock is added and where the lock is released for clearer expression

How to add and release locks? JDK5 provides a new Lock object Lock

The Lock implementation provides a wider range of locking operations than using synchronized methods and statements

Lock provides methods for obtaining and releasing locks

  • void lock(): get lock
  • void unlock(): release the lock

Lock is an interface that cannot be instantiated directly. Its implementation class ReentrantLock is used to instantiate it here

Construction method of ReentrantLock

  • Reentrantlock(): create an instance of ReentrantLock
package com.study_11;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements Runnable {
    private int tickets = 100;
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();
                if (tickets > 0) {
                    // Simulate the ticket selling time through the Sleep() method class
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "The second is being sold" + tickets + "Ticket");
                    tickets--;
                }
            } finally {
                lock.unlock();
            }
        }
    }
}
package com.study_11;

public class SellTicketDemo {
    public static void main(String[] args) {
        // Create an object of SellTicket class
        SellTicket st = new SellTicket();

        // Create three Thread class objects, take the SellTicket object as the parameter of the construction method, and give the corresponding window name
        Thread t1 = new Thread(st,"Window 1");
        Thread t2 = new Thread(st,"Window 2");
        Thread t3 = new Thread(st,"Window 3");

        // Start thread
        t1.start();
        t2.start();
        t3.start();
    }
}

10. Synchronized lock upgrade

jdk7.0 synchronized Major changes have been made:
	synchronized Applying for locks directly to the operating system consumes too much resources and is too heavy.
Oracle Modifications were carried out:
	1,Unlocked state (bias lock)
	2,The lock will be upgraded from bias lock to spin lock( CAS)
		CAS(compare and swap): Compare and exchange
		Spin locks can easily cause: ABA problem
	3,Spin lock upgraded to heavyweight lock
CAS And optimistic lock and pessimistic lock:
	The concept of optimistic locking: the task thread will never cause concurrency problems
	Pessimistic lock: as long as concurrency occurs, thread safety problems will arise
	Pessimistic lock: it solves the concurrency problem, but it is inefficient
	Optimistic lock: add a version number to the data without locking. Whenever the value changes, add 1 to the version number. Finally, judge whether it is concurrent by comparing the versions

11.volatile keyword

High concurrency: visibility, ordering, atomicity

In the case of multithreading, each thread has an execution stack independently. Each thread has independent useful data, and the memory is invisible to each other

stay java In, volatile Keywords have two core functions:
	1,Variables modified by it can break the memory barrier in multithreading, that is, variables modified by it have visibility.
	2,Prohibit instruction reordering!!!

12. Use of synchronized in singleton mode

gof 23 Medium design mode:
	|-- Decorator design mode
	|-- Singleton design pattern
		The construction method must be privatized.
		|-- Hungry Han style
			Create objects directly on attributes, static,Directly by the memory, the program does not exit, and the memory is not released
			This is very good. There is no thread safety problem. The only defect is that the memory will be occupied and will not be released whether it is used or not
		|-- Lazy style
			When you need to use objects, you can create objects again, which solves the hungry man's memory occupation problem.
			Lazy is not directly used in multithreading because it is non thread safe.

			If you want to solve thread safety problems,Locking is required:
			|-- Lock the method directly,Thread safety is solved directly,But the efficiency is not high(The range of the lock is too large)
			|-- Lock the code that creates the object(The range of the lock is small and the efficiency is high)
				|-- If you write this way, you need to judge it twice

13. Thread life cycle

fourteen ✨ deadlock

Deadlock( dead lock): 
	In the case of multithreading, the thread safety problem is solved by locking.

	Deadlock: be sure to avoid it!!! It causes a lot of data waste and can not solve the problem at the same time.

	Deadlock avoidance: an excellent solution: banker algorithm

	There are four necessary conditions for deadlock formation:
		|-- mutex
		|-- Request hold
		|-- Loop waiting
		|-- Inalienable conditions

	Deadlock is a waste of resources. In normal programming, deadlock must be avoided

👀date8.11—

15. Use of atomic classes

java.util.concurrent.atomic The classes under this package are atomic!!!
	
	Operator:
		Self addition		// i++ ==> t = i+1;  i = t; 
		Self subtraction
		+=		// i += 3 ==> t = i + 3; i = t;
		-=
	Without atomicity, thread safety problems will occur in the case of multithreading
	AtomicInteger All methods of these classes are atomic methods implemented using spin locks

16.ThreadLocal

The thread object provides a copy object, which is characterized in that each thread owns it independently ThreadLocal object
 Multithreading is generally preferred ThreadLocal,In the case of multithreading, save the value to
ThreadLocal In, multithreads have their own values and will not fight

set()		// Add values in your own thread
get()		// Gets the value stored in ThreadLocal in its own thread
remove()	// Finally, be sure to remove the value!!!, Otherwise, it is prone to memory overflow

17. Object reference of Java

Strong reference:
		Object o = new Object();
		o It is a strong reference and will not be used gc Recycle, even when calling System.gc();
		// o = null;
	
|-- Atomicity:
	java.util.concurrent.atomic Class based on atomicity under package
		AtomicInteger
		AtomicLong
		AtomicBoolean
|-- ThreadLocal object
	Private object per thread
	get()
	set()
	remove()
	Thread Precautions for use
|-- ThreadLocal Underlying source code
|-- java of
 object reference
	|-- Strong reference
	|-- Soft reference
	|-- Weak reference
	|-- Virtual reference

18. Producer and consumer models

Producer consumer model

Producer consumer model is a very classic multi-threaded cooperation model. Understanding the producer consumer problem can make us have a deeper understanding of multi-threaded programming

In fact, there are two types of threads:

  • One is the producer thread used to produce data
  • One is consumer thread, which is used to consume data

In order to decouple the relationship between producers and consumers, shared data areas are usually used, just like a warehouse

  • The producer's production data is directly placed in the shared data area, and does not need to care about the behavior of consumers
  • Consumers only need to obtain data from the shared data area, and do not need to care about the behavior of producers

In order to reflect the wait and wake-up during production and consumption, Java provides several methods for us to use. These methods are the wait and wake-up methods of Object class in Objec class:

Producer consumer case

package com.study_12;

public class Box {
    // Define milk quantity
    private int milk;
    // Define a member variable to represent the status of the milk box
    private boolean state = false;

    // Provides the operation of storing milk
    public synchronized void put(int milk) {
        // If there is milk, wait for consumption
        if (state) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // If not, produce milk
        this.milk = milk;
        System.out.println("The milkman will"+this.milk+"Put a bottle of milk into the milk box");

        // After production, modify the milk box status
        state = true;

        // awaken
        notifyAll();

    }

    public synchronized void get() {
        // If not, wait for production
        if(!state) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // Consume if you have
        System.out.println("The user gets the second"+this.milk+"Bottle milk");
        state = false;
        // awaken
        notifyAll();
    }

}
package com.study_12;

public class Customer implements Runnable{
    private Box b;
    public Customer(Box b) {
        this.b = b;
    }

    @Override
    public void run() {
        while (true){
            b.get();
        }

    }
}
package com.study_12;

public class Producer implements Runnable{
    private  Box b;
    public Producer(Box b) {
        this.b = b;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 5; i++) {
            b.put(i);
        }
    }
}
package com.study_12;

public class BoxDemo {
    public static void main(String[] args) {
        // Create a milk box formation, which is a shared data area
        Box b = new Box();

        // Create a producer object and pass the milk box object as a constructor parameter, because the operation to store milk is called in this class
        Producer p = new Producer(b);
        // Create a consumer object and pass the milk box object as a constructor parameter, because the operation to store milk is called in this class
        Customer c = new Customer(b);

        // Create two thread objects
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);

        // Start thread
        t1.start();
        t2.start();

    }
}

19. Thread pool

Thread pool:
	Pool mode: create a large number of objects we need in advance and put them in a pool (concept),
	The object is created in advance and does not need to be destroyed, so it is more efficient
		Advantages: it is more efficient and avoids repeated creation and destruction of objects
		Disadvantages: the memory occupation is high, and the number of pools is difficult to control


	Controlling the number of pools is the most critical issue

java Thread pool is 1.5 provide juc In the package, the underlying implementation is actually Callable and Future Interface
	|-- Depending on the situation, we create thread pools for many different scenarios

20. Use of several common containers under high and fat

Use of several common containers under high parallel distribution
	ArrayList
	Vector
	LinkedList
	HashMap
	HashSet
	Hashtable
	......
	It is emphasized that thread safety exists in all containers

	|-- Thread safe:
		Vector: Added lock, benefit: no thread safety problem, disadvantage: poor efficiency

	|-- juc Package:
		|-- ConrrentHashMap	
		|-- CopyOnWriteArrayList
		|-- CopyOnWriteArraySet
		|-- ConrrentHashMap
	
		1,Thread safety
		2,Read write separation

Topics: Java