java basics-multithreading Basics

Parallel and Concurrent

Parallel: Multiple CPU instances or machines executing a piece of processing logic at the same time are truly simultaneous.

Concurrency: A CPU or a machine, through the CPU scheduling algorithm, makes the user appear to be executing at the same time, actually not at the same time from the CPU operation level. Concurrency often requires public resources, and the processing of public resources and the coordination between threads are the difficulties of concurrency.

Process and Thread

  1. Process

(1) A process is a run of a program in a processing mechanism

(2) A process includes both instructions to be executed and any system resources required to execute the instructions, such as CPU, memory space, I/O port, etc.
The system resources occupied by different processes are relatively independent.

A program is an ordered collection of instructions and data. It has no meaning of running itself. It is a static concept, while a process is an execution process of a program. It is a dynamic concept. Is the unit of system resource allocation.

A process is a program that runs in an operating system. It has separate running memory space, such as applications and background services. windows is an operating system that supports multiple processes. The larger the memory, the more programs can run at the same time. A process in java is a program running on a separate JVM.

  1. Thread
    (1) Threads produce multiple execution threads that are smaller execution units than process units.
    (2) It has no entrance or exit and must reside on a thread that triggers execution
    (3) All threads belonging to the same process share the system resources of that process, but switching between threads is much faster than switching between processes.
    (4) Usually a process contains several threads, which are the units of CPU scheduling and execution.
    (5) Threads are separate execution paths

Threads: Multiple tasks that a program runs apart. Each task is a thread and the thread is shared memory. For example, in qq, you can receive and send messages at the same time, but there is a memory footprint.

The java language treats threads or execution environments as encapsulated objects that contain the CPU and its own code and data and are controlled by virtual machines.

Note that many multithreads are simulated, and true multithreading refers to multiple CPUs, that is, multicores, such as servers. If it is a mini multi-threaded, in the case of a CPU, the CPU can only execute one code at the same time node, because the switch is fast, so there is an illusion of simultaneous execution.

Related core concepts
(1) Threads are paths that execute independently
(2) When a program is running, it does not create its own thread, and there are multiple threads in the background, such as the main thread, the gc thread
(3) main, called the main thread, is the entrance to the system and is used to execute the entire program
(4) In a process, if multiple threads are opened up, the running of threads is scheduled by the scheduler, which is closely related to the operating system and can not be interfered with artificially.
(5) When operating on the same resource, there will be the problem of resource seizure, which requires concurrency control.
(6) Threads incur additional overhead, such as CPU scheduling time and concurrency control overhead
(7) Each thread interacts in its own working memory, and improper memory control can cause inconsistencies in data.
(8) Threads do not necessarily execute immediately, CPU schedules dispatch
3. Benefits of using multithreading
Run multiple tasks at the same time to improve CPU efficiency

Shared memory, less resources, communication between threads

Asynchronous call to avoid blocking.

Microscopically, only one job can be executed at a time, but to achieve multithreading, multiple jobs must be executed simultaneously at a macro level.

Thread structure

Threads can be thought of as being made up of three parts in java:
1. Virtual CPU, encapsulated in the java.lang.Thread class, controls the entire thread
2. Executed code, passed to the Thread class, executed in order controlled by the Thread class
3. The data processed, passed to the Thread class, is the data to be processed during code execution.

Note: In java, the virtual CPU is reflected in the Thread class. When a thread is constructed, it is constructed by a construct method parameter.
Execute code to initialize operation data.

Advantages of multithreading

(1) Multithread programming is simple and efficient. Using multithreading, you can share data and resources between threads.
(2) Suitable for developing service programs, such as Web services
(3) Suitable for developing programs with multiple interfaces
(4) Suitable for programs with human-computer interaction and computational load.

Benefits of using multithreading:
1. Improving CPU utilization by performing multiple tasks simultaneously
2 Shared memory, less resources, communication between threads
3. Asynchronous calls to avoid blocking

The state of the thread

(1) When a Thread object is generated, a thread is generated. With this object instance, you can start a thread, terminate it, or suspend it temporarily.
(2) The Thread class itself is only the virtual CPU of the thread, and the code executed by the thread is accomplished by the run method (contained in a specific object) in the method, called the thread body. The object that implements the thread body is passed to the thread when it is initialized.
(3) After a thread is created and initialized, the java runtime system automatically calls the run() method.

1. Once a new New Thread object is created, it will only briefly be in this state. At this point he has allocated the necessary system resources and performed the initialization.

Thread thread = new Thread("test");

2. Ready Runnables are called Runnable States
After the thread object is created, other threads invoke the object's start() method to start the thread. for example
thread.start(). Threads in a ready state may be scheduled for execution by the CPU at any time.

3. Running Running: Threads get CPU privileges to execute. Note: Threads can only enter the running state from the ready state.

4. Death
(1) The last statement in the run() method is executed
(2) When a thread encounters an abnormal exit

5. Blocked
A thread that is executing is blocked because it is suspended for a particular reason. Threads do not queue in a ready queue when blocking. You must wait until the cause of the blocking is eliminated to enter the ready queue.
There are three types of blocking:
(1) Wait blocking: Allows a thread to wait for a job to complete by calling the thread's wait() method
(2) Synchronization blocking: When a thread fails to acquire a synchronised synchronization lock (because the lock is being used by another thread), it enters a synchronised blocking state.
(3) Other blockages: When a thread's sleep() is called or an I/O request is made, the thread enters a blocking state.
When the sleep() state times out, join() waits for the thread to terminate or times out. Or when I/O processing is complete, the thread is ready.

6. Break Threads
When the run() method execution ends and returns, the thread automatically ends.
(1) interrupt() methods are often called in programs to terminate threads. This method can not only interrupt running threads, but also end up in blocked
Stateful thread, which throws an InterruptedException exception
.
A method to test if a thread is interrupted in java
(1)void Interrupt() sends an interrupt request like a thread, setting the thread's "Interrupted" to true
(2)static boolean interrupted() detects if the current thread has been interrupted, resets the state "interrupted" value, and if called twice in a row
This method returns false on the second call
boolean isInterrupted() detects if the current thread has been interrupted without changing the value of "interrupted"

Create Threads

One way to construct the class Thread is as follows

public Thread(ThreadGroup group,Runnable target,Strig name)
//Group specifies the thread group to which the thread belongs; target is the object where the thread body run() method resides
(target Must be implemented Runnable Interface; name Is the name of the thread.
//There is only one run() method as the thread body in the interface Runnable.
Any implementation Runnable The object of the interface can be the target object of a thread

First, the method of creating a current thread - inheriting the Thread class

public class ThreadTest{
    /**
     * Method one for creating threads, inheriting the Thread class*/
    static Lefthand left;
    static Righthand right;

    public static void main(String[] args) {
        left = new Lefthand();
        right = new Righthand();

        left.start();
        right.start();
    }
}

class Lefthand extends Thread{
    /**
     * The method run() is called the thread body, and it is the core of the whole thread. The code for the tasks the thread is about to complete is defined in the thread body
     * In fact, the difference between different functions is that they have different threads.*/
    public void run(){
        for (int i = 0; i < 6; i++) {
            System.out.println("You are Students!");
            try {
            	//Multithreaded to rest
                sleep(500);//Performance Improvement
                System.out.println(getState());

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Righthand extends Thread{
    public void run()
    {
        for (int i = 0; i < 6; i++) {
            System.out.println("I am a Teacher!");
            try {
                sleep(400);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2. Implement Runnable() interface
In summary, threads are referenced by instances of Thread objects. The code executed by the thread comes from the class referenced by the parameter passed to the Thread constructor, which
The interface Runnable() must be implemented, and the data for thread operations comes from the Runnable instance that touches the bottom of the Thread constructor.......

import javax.swing.plaf.TableHeaderUI;

public class xyz implements Runnable{
    int i=0;
    @Override
    public void run() {
        while (i < 100){
            System.out.println("Hello" + i++);
            try {
                Thread.sleep(500);  //sleep() is a static method in the Thread class, so it can be called directly
                //The parameter specifies the minimum amount of time a thread must sleep before starting again to ensure that it returns to the ready queue after a period of time.
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
/**
 *public Thread(ThreadGroup group,Runnable target,String name
 * group Indicates the thread group to which the thread belongs; target is the object where the thread body run() method is located, and name is the name of the thread*/

/**
 * Thread The construction method contains a parameter for a Runnable instance, which means that you must define a class that implements the Runnable interface and produce an instance of that class.
 * A reference to this instance is the parameter appropriate for this construction method*/
class test{
    public static void main(String[] args) {
        Runnable r = new xyz();
        Thread t = new Thread(r);
        t.start();
    }
}


Summary: Threads are referenced by instances of Thread objects. The code executed by the thread comes from a class referenced by the parameter passed to the Thread constructor, which must implement the Runnable() interface, and the data the thread does comes from the Runnable instance passed to the Thread constructor.

A discussion of two ways to create threads

1. Suitable for implementation of Runnable interface method
Because Java only allows single inheritance, if a class already inherits Thread, it no longer inherits other classes.
In some cases, the implementation of the Runnable interface is forced.

2. Suitable for inheriting the Thread method
When a run() method is placed in the Thread class, this actually refers to the Thread instance that controls the current running system

Five, Thread Startup

A thread is created but does not run immediately. For threads to really run in a java environment, they must be started by the start() method.
After startup, the thread's virtual CPU is ready.

1.start() is used to start a thread. When the start() method is called, the system will start a thread. The thread started by the start() method in the Thead class is ready (runnable) and not running. Once the CPU time slice is obtained, the run() method will start automatically. There is no need to wait for the run () method to finish executing, but you can continue with the code below, so you can see that the run () method does not implement multithreading.
2.run() is used to define actions that are performed by a lock after a thread object is dispatched, and the user must override the run() method
3.yield() forces the current thread to terminate
4.isAlive() tests if the current thread is active
5.sleep(int millsecond) allows the thread to rest for a period of time, depending on the parameters
6.void wait() keeps the thread waiting

Sixth, thread scheduling

Although the ready thread is ready to run, this does not mean that it must run immediately.
Time scheduling in Java is usually preemptive, not time slice.

Preemptive scheduling means that there may be multiple threads ready to run, but only one is actually running. A thread gets execute, and the thread keeps running.
Until it finishes running or is blocked for some reason, or another high priority thread is ready.

java uses the following priority policy for thread scheduling
1. Execute first with higher priority and execute later with lower priority
2. Multithreaded systems automatically assign a priority to each thread, inheriting the priority of its parent class by default
3. Task rescue threads have a higher priority
4. Threads of the same priority follow the principle of "first in, first out"

Several static variables related to thread priority in the Thread class in java
1.MAX_PRIORITY value is 10
2.MIN_PRIORITY
3.NORM_PRIORITY value is 5

Several common priority-related methods in java classes are
1.void setPrioriy(int newPriority)
2.int getPriority() gets the priority of the current thread
3.static void yield() causes the current thread to discard execution

Ready and Blocked Queues
1. All threads that are ready but not running are queued according to their priority. When the CPU is idle, if the ready queue is not empty, the first thread in the queue with the highest priority will run.
2. When a thread is preempted and stops running, its running state is changed and placed at the end of the ready queue, and the same thread blocked for some reason is ready
Usually it is also placed at the end of the ready queue.

Basic control of seven threads

1. End Thread
In program code, you can use the static method currentThread() in the Thread class to reference a running thread.

2. Check Threads
isAlive gets information about whether a thread is still active. Active state does not mean that the thread is executing, it just means that the thread has been started.
There are no methods to run either stop() or run().

3. Suspend Threads
Suspending a thread is also known as suspending. After suspending, you must wake up the thread again to run.

sleep()
Threads do not wake up immediately after the sleep period has expired, because other threads may be executing at this time, and rescheduling occurs only in the following circumstances:
.... The awakened thread has a higher priority
.... Executing thread blocked for other reasons
.... The program is in a system that supports time slices

wait() and notify()/notifyAll()
The wait() method causes the current thread to wait until another thread calls the notify() or nitifyAll() issue of this object to wake up the thread

join()
The method join() causes the existing thread to wait until the end of the thread called by the method join() method. For example, a thread tt has been generated and run,
The method timeout() is executed in another thread,

public void timeout(){
    //Pause the thread until the other thread finishes
    tt.join;
    //Continue executing the thread after the other thread has finished
}

Eight Synchronization Issues

Thread Security and Atomicity

Since memory can be shared between threads, an object (variable) can be shared by multiple threads and accessed simultaneously by multiple threads. When multiple threads access a class, the class behaves correctly regardless of how the runtime environment is scheduled or how the processes are to be executed alternately, and no additional synchronization synergies are required in the main code, then the thread is synchronized.

1. Inter-thread communication, writing threads enter information into the pipeline flow, reading threads read information into the pipeline flow.
2. Resource mutually exclusive sharing between threads
Typically, some threads running at the same time need to share data. In this case, each thread needs to consider working with it
The state and behavior of other threads sharing data, otherwise the consistency of shared data cannot be guaranteed.

import javax.swing.plaf.TableHeaderUI;
import java.io.*;
import java.util.Scanner;
import java.util.Stack;

class myWriter extends Thread{
    private PipedOutputStream outStream;
    private  String messages []  = {"Monday","Tuesday","Wednsday",
    "Thursday","Friday","Saturday","Sunday"};
    public myWriter(PipedOutputStream o){
        outStream = o;
    }

    public void run(){
        /**
         * Creates a new print stream, without automatic line flushing, with the
         * specified OutputStream. Characters written to the stream are converted
         * to bytes using the platform's default character encoding.
         *
         * @param  out        The output stream to which values and objects will be
         *                    printed
         *
         * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)
         *
         *  public PrintStream(OutputStream out) {
         *             this(out, false);
         *         }
         */

        PrintStream p = new PrintStream(outStream);
        for (int i = 0; i < messages.length; i++) {
            p.println(messages[i]);//Write data into the pipeline flow,
            p.flush();
            System.out.println("Write:" + messages[i]);
        }
        p.close();
        p = null;
    }
}

class myReader extends Thread{
    private PipedInputStream inputStream;
    public myReader(PipedInputStream i){
        inputStream = i;
    }

    public void run(){
        String line;
        boolean reading = true;
        Scanner scan = new Scanner(new InputStreamReader(inputStream));

        while (scan.hasNextLine()){
            System.out.println("Read:" + scan.nextLine());

            try {
                Thread.currentThread().sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

public class Pipethread{
    public static void main(String[] args) {
        Pipethread thisPipe = new Pipethread();
        thisPipe.process();
    }

    private void process() {
        PipedInputStream inputStream;
        PipedOutputStream outputStream;
        try {
            /**
             * Creates a piped output stream that is not yet connected to a
             * piped input stream. It must be connected to a piped input stream,
             * either by the receiver or the sender, before being used.
             *
             * @see     java.io.PipedInputStream#connect(java.io.PipedOutputStream)
             * @see     java.io.PipedOutputStream#connect(java.io.PipedInputStream)
             *
             * public PipedOutputStream() {
             *             }
             */

            outputStream = new PipedOutputStream();
            /**
             * Creates a {@code PipedInputStream} so
             * that it is connected to the piped output
             * stream {@code src}. Data bytes written
             * to {@code src} will then be  available
             * as input from this stream.
             *
             * @param      src   the stream to connect to.
             * @throws     IOException  if an I/O error occurs.
             *Insert a code snippet here
             * public PipedInputStream(PipedOutputStream src) throws IOException {
             *                 this(src, DEFAULT_PIPE_SIZE);
             *             }
             */

            inputStream = new PipedInputStream(outputStream);
            new myWriter(outputStream).start();
            new myReader(inputStream).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Lock flag of object
In the java language, the concept of object mutex is introduced to synchronize shared data operations between different threads, and the concept of object mutex prevents multiple threads from accessing the same conditional variable at the same time. java can have an object mutex for each instance of an object.

Visibility, atomicity, and ordering in the java memory model.
Visibility: When multiple threads access the same variable x, thread 1 modifies the value of variable x, thread 1, thread 2... thread n can immediately read the modified value of thread 1.
Orderliness: The execution of a program in the order in which the code is written. In the java memory model, the compiler and processor are allowed to reorder instructions, but the reordering process does not affect the execution of a per-threaded program, but it does affect the correctness of multithreaded concurrent execution.
Atomicity: Atomicity usually means that there is no partial or complete execution of multiple operations.

Thread pool concept
Threads are memory intensive when they are created, so we need to create several executable threads in advance and put them into a pool. When needed, they are taken directly out of the pool without creating them. When used, they are put into the pool without destroying them, which reduces the overhead of creating and destroying objects.
ExecutorService: Thread pool interface
ExecutorService poo = Executors. Common thread pool name;
Common thread pools:
newsingleThreadExecutor: A pool of threads with a single thread, where only one thread is working at a time and a single thread executes tasks serially
newfixedThreadExecutor(n): A fixed number of thread pools, one thread per task submitted until the maximum number of thread pools is reached, and then wait for the threads in front of the queue to execute or destroy later
newCacheThreadExecutor: A cacheable thread pool. When the thread pool exceeds the number of threads required to process tasks, some idle threads (typically 60s) are recycled. When there are tasks coming and threads are not enough, the thread pool creates new threads and calls the threads in the pool when they are sufficient. Suitable for a large number of less time consuming threaded tasks.
newScheduleThreadExecutor: An infinite-sized thread pool for performing delayed tasks or fixed weeks
Period of tasks.

package ThreadPool;

public class ticket implements Runnable{
    private int ticket = 10;

    @Override
    public void run() {
        for (int i = 1; i <= 15; i++) {
            if (ticket > 0)
                System.out.println(Thread.currentThread().getName()+"Buy tickets, remaining"+ticket--);
            else {
                System.out.println(Thread.currentThread().getName()+"Ticket sold out");
                break;
            }

        }
    }
}

package ThreadPool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TicketPool {
    public static void main(String[] args) {
        /**
         * Create threads using thread pools
         * */

        //Creating a five-threaded thread pool Executors is a class
        ExecutorService service = Executors.newFixedThreadPool(5);

        for (int i = 1; i < 5; i++) {
            //Execution Thread
            service.execute(new ticket());
        }
        service.shutdown();//Close Thread Pool
    }
}

(1) Declare a shared data (variable) with the keyword volatile
volatile is visible, ordered, and not atomic.
Visibility: When multiple threads access the same variable x, thread 1 modifies the value of variable x, thread 1, thread 2,... Thread n can immediately read the modified value of thread 1.
Orderliness: The execution of a program in the order in which the code is written. In the java memory model, the compiler and processor are allowed to reorder instructions, but the reordering process does not affect the execution of a single-threaded sequence, but it does affect the correctness of multithreaded concurrent execution.
Atomicity: Atomicity usually means that there is no partial or complete execution of multiple operations.

Blocking synchronization when synchronised is called a heavy lock. Volatile is a non-blocking synchronization called a lightweight lock. Variables decorated with volatile ensure that each thread can occasionally get the latest value of the variable.

(2) Use the keyword synchronized to declare a method or piece of code for manipulating shared data. Synnisedis java's built-in locking mechanism and is on the JVM.

(3)ReentrantLock can be re-locked, and a new java.util.concurrent package has been added to javaSE5.0 to support synchronization. ReentrantLock classes are re-entrant, mutually exclusive, and absorb locks from the Lock interface. It has the same basic behavior and semantics as using synchronised methods and blocks, and extends its capabilities.
ReentrantLock(): Create a ReentrantLock instance
lock(): Get a lock
unlock(): release lock
Reentrant: A releases the lock after it has been acquired or the lock fails, B can continue to acquire the lock.

To ensure the integrity of data operations
pan.baidu.com/s/1LmovqR4vuN8pxoRsnzCN6A
When a thread executes a synchronized statement, it sets the object parameter passed as a lock flag, which prevents other threads from accessing the object.

When the first thread has a lock tag, if another thread attempts to execute a statement in synchronised(this), it will get the lock tag from the object this.
The thread cannot continue execution because this tag is not available. In fact, the thread will join a wait sequence that is connected to the object lock flag, and when the tag is returned to the object, the first thread waiting for it will get him and continue execution. This flag is automatically returned when the thread holding the lock flag runs through the synchronized() call to the contained block.

Synchronization method

class myStack1{
    int idx = 0;
    char data [] = new char[6];

    public void push(char c){
        synchronized (this){
            data[idx] = c;
            idx++;
        }
    }

    public synchronized char pop(){
        synchronized (this){
            idx--;
            return data[idx];
        }
    }
}

deadlock

If a thread holds one lock and attempts to acquire another, there is a risk of deadlock.
Deadlock occurs when the first thread waits for a lock held by the second thread, while the second thread waits for a lock held by the first thread.
No thread can continue execution

Thread Interaction

1. Why do threads need to interact with each other?
2. To solve the problem of thread speed, java provides an interactive method based on object instances. Every object instance in java has two thread queues connected to it. The first uses thunder to arrange the threads waiting for the lock flag, and the second implements the interaction between wait() and notify().
(1) The wait() method allows the current thread to release its object mutex and enter the wait queue (wait queue)
(2) The notify() and notifyAll() methods wake up one or all threads waiting in a queue and move them into a queue waiting for mutually exclusive locks on the same object
Note: All three methods can only be called in methods or code snippets declared synchronised.

Production consumer model

Tags: Java Hibernate Spring Concurrent Programming

Posted on Sun, 28 Nov 2021 17:28:55 -0500 by nate2687