The 26th day of learning big data - supplementing IO stream and multithreading

Posted by villas on Sun, 20 Feb 2022 19:16:41 +0100

Day 26 of learning big data - Supplementary IO stream and multithreading (1)

Summary of multithreading:

1, Overview of multithreading:

Process:
The running program is an independent unit of the system for resource allocation. Each process has its own memory space and resources

Thread:
It is a single sequential control flow of a process, or a separate execution path
If a process has only one execution path, it is called single thread
If a process has multiple execution paths, it is called multithreading

Examples: mine sweeping, 360 anti-virus software, baidu online disk

Understand three key words:
1. Serial means that all tasks in a program are executed in sequence. When the previous task has not been processed, the next task will not be processed
For example: there is only one barber in a barber shop. Many people go to have their hair cut. First wait for the person in front of them to have their hair cut, and then it's their turn to the person behind them.
2. Parallelism refers to assigning tasks to different processors for processing, and then serial processing in each processor.
For example: there are many windows in the railway station. Multiple windows sell tickets at the same time, but for one window, one person sells tickets one by one
3. Concurrency is essentially a phenomenon. Concurrency needs the support of the processor. For example, when a task is delivered, the operating system can call and process other tasks, whether serial or parallel
All need the support of the operating system for concurrency. Assuming that drinking water is a task, the conductor of each railway station can drink water while selling tickets, which supports concurrency.

Multithreaded interview question 1:

Is the JVM single threaded or multi-threaded at startup?
Multithreading:
Main (main thread)
Garbage collection thread
Therefore, when the JVM is started, the minimum requirement is that two threads exist, so the JVM is multi-threaded when it is started.

Multithreaded interview question 2:

The difference between calling start() and calling run():

The run() method only encapsulates the code executed by the thread, but there is no difference between calling run() directly and calling ordinary methods
To call the start() method, first start a thread separately, and then the JVM calls the run() method in the thread class

The first way to create a thread:

Inherit Thread class

1. Create a custom class to inherit the Thread class
2. This class needs to override the run method in the Thread class
Why the run() method?
When the thread starts, the code logic executed is only the code logic of the run() method
3. Create thread objects based on this class
4. Start thread

public static void main(String[] args) {
        //Each creation of an object is equivalent to the creation of a new thread object
//        MyThread1 myThread1 = new MyThread1();

        //Start thread
//        myThread1.run();
        //Simply calling the run method only means that an object calls an ordinary method, so here is still a single threaded program
        //To see the effect of multithreading, you must start the thread start() in another way
        //The run() method only encapsulates the code executed by the thread, but there is no difference between calling run() directly and calling ordinary methods
        //To call the start() method, first start a thread separately, and then the JVM calls the run() method in the thread class
//        myThread1.start();
        //When a thread object is started multiple times, an error is reported: IllegalThreadStateException illegal thread state exception
//        myThread1.start();

        System.out.println("==============================");
        //Simulate multithreading environment
        //Create at least 2 or more thread objects
        MyThread1 myThread1 = new MyThread1();
        MyThread1 myThread2 = new MyThread1();

        //Start thread
        myThread1.start();
        myThread2.start();

        /**
         *      matters needing attention:
         *          1,The start thread calls the start() method
         *          2,The start sequence of threads has no effect on the results
         */


    }
How to get the name of the thread?

How to set a name for a thread?
Name the thread through the construction method:
Thread(String name) assigns a new thread object.

How to get the name of the thread?
public final String getName() returns the name of this thread

How to get the thread where the 'main' method is located?

public static Thread currentThread() returns a reference to the thread object currently executing.

public class MyThread2 extends Thread {
    //If you want to get the name of the thread, you need to pass in the name, so the constructor has to pass in the thread name

    public MyThread2(){

    }

    public MyThread2(String name){
        super(name);
    }

    @Override
    public void run() {
        System.out.println("========================");
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }

    }
}
public static void main(String[] args) {
        //Create two thread objects
        //Name the thread through the construction method
        //Simulate multithreading environment, so the number of threads created is 2 or more
//        MyThread2 t1 = new MyThread2("yl");
//        MyThread2 t2 = new MyThread2("szh");
//
//        //Start thread
//        t1.start();
//        t2.start();

        //You can also use the setName method in the Thread method
        MyThread2 t1 = new MyThread2();
        MyThread2 t2 = new MyThread2();
        MyThread2 t3 = new MyThread2();

//        public final String setName() changes the name of this thread to be equal to the parameter name
        t1.setName("yl");
        t2.setName("szh");
        t3.setName("yzl");
        //Start thread
        t1.start();
        t2.start();
        t3.start();

        //How to get the thread of main method
        //public static Thread currentThread() returns a reference to the thread object currently executing.
        System.out.println(Thread.currentThread().getName());
    }

The second way to create a thread:

Implement Runnable interface
1. Customize a class to implement the Runnable interface
2. Run implementation method
3. Create custom class object
4. Create a Thread object and pass the custom object as a parameter to the construction method

public class MyRunnable1 implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            //Since there is no getName() method in the Runnable interface, the name of the thread object cannot be obtained here
            //Indirectly, we can get the object of the current Thread first, and then call the getName() method in the Thread class
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}
public class MyRunnableDemo1 {
    public static void main(String[] args) {

        //Create custom objects
        MyRunnable1 myRunnable1 = new MyRunnable1();

        //Create thread name
        Thread t1 = new Thread(myRunnable1);
        Thread t2 = new Thread(myRunnable1);

        //Name the thread
        t1.setName("yl");
        t2.setName("szh");

        t1.start();
        t2.start();
    }
}

Thread sleep, interrupt, comity, guard and join:

Thread sleep
Public static void sleep (long miles) / / 1 second = 1000 milliseconds
Thread join
public final void join()
Thread comity
public static void yield()
Background thread
public final void setDaemon(boolean on)
Interrupt thread
public final void stop()
public void interrupt()

Thread sleep Demo:
public class MySleepThread extends Thread{
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
            //Method of adding sleep
            //public static void sleep(long millis)
            //Stop for 1 second, 1 second = 100 milliseconds
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
public class ThreadSleepDemo {
    public static void main(String[] args) {
        MySleepThread t1 = new MySleepThread();
        MySleepThread t2 = new MySleepThread();
        MySleepThread t3 = new MySleepThread();

        //Set a name for the thread
        t1.setName("yl");
        t2.setName("szh");
        t3.setName("yzl");

        //Start thread
        t1.start();
        t2.start();
        t3.start();
    }
}
Thread interrupt:
Note the difference between stop() and interrupt:

t1.stop(); // Forced sleep interruption, program stop, this method has been deprecated
t1.interrupt(); // When sleep is interrupted, the code behind the run method continues to execute. After execution, an exception is thrown

import java.util.Date;

public class MyStopThread extends Thread{
    @Override
    public void run() {
        System.out.println("Start execution time:"+new Date());

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

        System.out.println("End time:" + new Date());
    }
}
/*
    Interrupt thread
        public final void stop()
        public void interrupt()

 */
public class ThreadStopDemo {
    public static void main(String[] args) {

        MyStopThread t1 = new MyStopThread();

        t1.setName("floret");

        t1.start();
        try {
            Thread.sleep(3000);
//            t1.stop();// Forcibly interrupt sleep and the program stops. This method has been deprecated
            t1.interrupt();
            //When sleep is interrupted, the code behind the run() method continues to execute. After execution, an exception InterruptedException is thrown
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Thread joining:

Join thread
public final void join()
The purpose of calling join by thread object is to make the current thread execute first, and then other threads execute
In other words, other threads wait for the thread calling the join to execute before executing.

be careful:
The call of join must be after start.

Note: the purpose of thread object calling join is to let the current thread execute first, and then other threads execute. In other words, other threads wait for the thread calling join to execute. That is, the call of join must be after start.
public class MyJoinThread extends Thread{
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}
/*
    Join thread
        public final void join()
        The purpose of calling join by thread object is to make the current thread execute first, and then other threads execute
        In other words, other threads wait for the thread calling the join to execute before executing.

       be careful:
       join The call of must be after start.

 */
public class ThreadJoinDemo {
    public static void main(String[] args) {
        MyJoinThread t1 = new MyJoinThread();
        MyJoinThread t2 = new MyJoinThread();
        MyJoinThread t3 = new MyJoinThread();

        //Thread setting name
        t1.setName("yl");
        t2.setName("szh");
        t3.setName("yzl");

        //Start thread
        t1.start();

        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t2.start();
        t3.start();

    }
}
Thread comity:

Comity thread:
public static void yield()
Pauses the currently executing thread object and executes other threads
Its function is to make multiple threads look more harmonious when running, but it does not guarantee that multiple threads can be run once.

public class MyYieldThread extends Thread {
    @Override
    public void run() {
        for(int i=1;i<=200;i++){
            System.out.println(getName()+":"+i);
            Thread.yield();
        }
    }
}
/*
        Comity thread:
        public static void yield()
        Pauses the currently executing thread object and executes other threads
        Its function is to make multiple threads look more harmonious when running, but it does not guarantee that multiple threads can be run once.

 */
public class ThreadYieldDemo {
    public static void main(String[] args) {
        //Create 2 Thread objects to simulate multithreading
        MyYieldThread t1 = new MyYieldThread();
        MyYieldThread t2 = new MyYieldThread();

        //Name the thread
        t1.setName("yl");
        t2.setName("szh");

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

    }
}
Thread guard

There are two kinds of threads in Java: user thread and daemon thread

User thread: before learning multithreading, the running threads are user threads

Daemon thread: the so-called daemon thread refers to a general service thread provided in the background when the program is running. For example, the garbage collection thread is a daemon thread
And this thread does not necessarily exist, so conversely, as long as the program has a daemon thread, the program will not terminate.

How to set the daemon thread?
public final void setDaemon(boolean on)

be careful:
1. The daemon thread must be set before starting
    2,When the running program has only one thread and this thread is a guard thread, Java Virtual machine exit (program stop)
public class MyDaemonThread extends Thread{
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}
/*
    Background thread: (daemon thread)
    public final void setDaemon(boolean on)

    Java There are two kinds of threads in: user thread and daemon thread

    User thread: before learning multithreading, the running threads are user threads

    Daemon thread: the so-called daemon thread refers to a general service thread provided in the background when the program is running. For example, the garbage collection thread is a daemon thread
        And this thread does not necessarily exist, so conversely, as long as the program has a daemon thread, the program will not terminate.

    How to set the daemon thread?
        public final void setDaemon(boolean on)


    be careful:
        1,The daemon thread must be set before starting
        2,When the running program has only one thread and this thread is a guard thread, the Java virtual machine exits (the program stops)


 */
public class ThreadDaemonDemo {
    public static void main(String[] args) {

        //Create 3 threads
        MyDaemonThread t1 = new MyDaemonThread();
        MyDaemonThread t2 = new MyDaemonThread();
        MyDaemonThread t3 = new MyDaemonThread();

        //Name the thread
        t1.setName("Liu Bei");
        t2.setName("Guan Yu");
        t2.setDaemon(true);
        t3.setName("Fei Zhang");
        t3.setDaemon(true);

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

Threads have two scheduling models:
In the time-sharing scheduling model, all threads use the right to use the CPU in turn, and the time slice occupied by each thread is evenly distributed
The preemptive scheduling model gives priority to the threads with high priority to use CPU. If the threads have the same priority, one will be selected randomly. The threads with high priority get relatively more CPU time slices.
Java uses a preemptive scheduling model.
Demonstrates how to set and get thread priority
public final int getPriority()
public final void setPriority(int newPriority)

Summary:

1. The default priority for threads is 5
2. The thread priority range is 1-10
3. High thread priority only means that the probability of obtaining CPU time slice will be higher, but it is not absolutely obtained

public class MyPriorityThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 200; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}
/*
        We didn't set priority in the first few codes, and we guessed that there would be a default priority.
        What is the default priority? five

        Method to get thread priority:
        public final int getPriority()Returns the priority of this thread.
        How to set thread priority:
        public final void setPriority(int newPriority)Change the priority of this thread.

        public final static int MAX_PRIORITY = 10;  The maximum priority a thread can have.
        public final static int MIN_PRIORITY = 1;   The minimum priority a thread can have.

      Summary:
        1,The default priority for threads is 5
        2,The thread priority range is 1-10
        3,High thread priority only means that the probability of obtaining CPU time slice will be higher, but it is not absolutely obtained


 */
public class ThreadPriorityDemo {
    public static void main(String[] args) {
        //The priority of the main thread is 5
//        System.out.println(Thread.currentThread().getPriority());
        MyPriorityThread t1 = new MyPriorityThread();
        MyPriorityThread t2 = new MyPriorityThread();
        MyPriorityThread t3 = new MyPriorityThread();

        //Get the priority of T1, T2 and T3 threads
//        System.out.println(t1.getPriority());
//        System.out.println(t2.getPriority());
//        System.out.println(t3.getPriority());

        //set priority
        //IllegalArgumentException illegal parameter passed in
//        t1.setPriority(100);

        //newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY
        t1.setPriority(10);
        t2.setPriority(1);
        t3.setPriority(2);

        //Name the thread
        t1.setName("yl");
        t2.setName("szh");
        t3.setName("yzl");

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

}

Introduce classic cases to illustrate multithreading step by step

Ticket selling system

The first step is to try:
public class TicketWindow1 extends Thread {

    private static int tickets = 100;

    @Override
    public void run() {
        //It is problematic to define 100 tickets in the run method
        //Each thread will execute the run method. In this way, each thread has its own 100 tickets
        //Therefore, it is inappropriate for us to define 100 tickets here.
        //If it is defined as a static global variable, it is found that the order is still wrong after trying. Maybe when window 1 sells the 89th sheet, window 3
        //Only sold 97, how to solve it?
//        int tickets = 100;
        while(true){
            if(tickets > 0){
                System.out.println(getName()+"In the process of sale"+(tickets--)+"Ticket");
            }else{
                break;
            }
        }
    }
}
/*
        A cinema is currently showing a New Year blockbuster, with a total of 100 tickets, and it has three ticket windows. Please design a program to simulate the ticket sales of the cinema.
        Two ways to achieve
            Inherit Thread class

 */
public class SellTicketDemo1 {
    public static void main(String[] args) {
        //Create three ticket windows to simulate the ticket selling process
        TicketWindow1 window1 = new TicketWindow1();
        TicketWindow1 window2 = new TicketWindow1();
        TicketWindow1 window3 = new TicketWindow1();

        //Name the thread
        window1.setName("Window 1");
        window2.setName("Window 2");
        window3.setName("Window 3");

        //Start thread
        window1.start();
        window2.start();
        window3.start();
    }
}
The second way to try:
public class TicketWindow2 implements Runnable{
    //Variables that are not set to static
    private int tickets = 100;

    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName() + "In the process of sale" + (tickets--) + "Ticket");
            }else{
                break;
            }
        }
    }
}
/*
    A cinema is currently showing a New Year blockbuster, with a total of 100 tickets, and it has three ticket windows. Please design a program to simulate the ticket sales of the cinema.
    Two ways to achieve
    Implement Runnable interface

 */
public class SellTicketDemo2 {
    public static void main(String[] args) {
        TicketWindow2 ticketWindow2 = new TicketWindow2();

        //Create a thread object and simulate three windows
        Thread window1 = new Thread(ticketWindow2);
        Thread window2 = new Thread(ticketWindow2);
        Thread window3 = new Thread(ticketWindow2);

        //Name
        window1.setName("yl");
        window2.setName("szh");
        window3.setName("yzl");

        //Start thread
        window1.start();
        window2.start();
        window3.start();
    }
}
The third way to try:

In order to get closer to reality, we add delay sleep
However, after adding the delay, two problems arise:
1. We sold the same ticket many times
The operation of CPU is caused by atomicity. Small and medium-sized time slices of CPU are enough to run many times
2. There are 0 votes and negative votes
The execution of threads is random and delayed. After adding sleep, the thread becomes blocked and allows other threads to execute.

public class TicketWindow3 implements Runnable{
    private int tickets = 100;

    @Override
    public void run() {
        //Window 1, window 2, window 3
        while (true) {
            //Window 1, window 2, window 3
            if (tickets > 0) { // 1
                //Window 1, window 2, window 3
                //In order to simulate a more realistic ticket selling scenario, we add delay
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "In the process of sale" + (tickets--) + "Ticket");
                //Window 1 is selling ticket 100
                //Window 2 is selling ticket 100
                //The reason for the duplication is that the operation of the CPU is atomic,
                //Since tickets -- is a two-step operation, assign the value first and then output--
                //At this time, the value of tickets 1 has not changed, and the value of tickets 2 has not been output in time
                //So the same ticket has been sold many times.

                //Ideally:
                //Window 1 is selling ticket 100
                //Window 2 is selling ticket 99

                //Explanation for the occurrence of ticket 0:
                //When the value of tickets is 1 for two or three windows at the same time, they all enter the if and sleep once
                //When the sleep of the first window ends and the printing ends, the value of tickets changes from 1 to 0
                //So when the later thread ends sleeping, the print result is 0
                //The source of negative numbers is the phenomenon that three threads may enter the if statement when the value of tickets is 1.

            }
        }
    }
}
/*
        In order to get closer to reality, we add delay sleep
        However, after adding the delay, two problems arise:
            1,We sold the same ticket many times
                CPU The operation of is caused by atomicity. Small and medium-sized time slices of CPU are enough to run many times
            2,There are 0 votes and negative votes
                The execution of threads is random and delayed. After adding sleep, the thread becomes blocked and allows other threads to execute.

 */
public class SellTicketDemo3 {
    public static void main(String[] args) {
        //1. Create custom class object
        TicketWindow3 ticketWindow2 = new TicketWindow3();

        //2. Create three thread objects and simulate three windows
        Thread window1 = new Thread(ticketWindow2);
        Thread window2 = new Thread(ticketWindow2);
        Thread window3 = new Thread(ticketWindow2);

        //3. Name the thread object
        window1.setName("Window 1");
        window2.setName("Window 2");
        window3.setName("Window 3");

        //4. Start thread
        window1.start();
        window2.start();
        window3.start();
    }
}
The fourth way to try:

Java provides a mechanism for us to use to solve the problem of thread safety: synchronous safety mechanism

Solution: a piece of code synchronization
Statement format:
Format:
Synchronized (object) {code that needs to be synchronized;}
1. What is the object here?
Try creating any object
2. What code needs to be synchronized?
Code for multiple statements to operate on shared data

public class TicketWindow4 implements Runnable{
    private int tickets = 500;
    private Object object = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (object){
                if (tickets > 0) {
                    //In order to simulate a more realistic ticket selling scenario, we add delay
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "In the process of sale" + (tickets--) + "Ticket");

                }
            }
        }
    }
}
/*
        In the previous case, the delayed operation was added. The problem is actually called thread safety.
        To solve this problem, we must find out what causes the problem:
        (Three points to sum up whether thread safety problems will occur (none of them is indispensable)
        1,Is there a multithreaded environment
        2,Is there shared data / shared variables
        3,Are there multiple statements operating on shared data / shared variables

        Recall whether the previous case meets the conditions for interpreting thread safety issues:
        1,Is there a multithreaded environment? There are three window threads
        2,Whether there is shared data / shared variable. The shared data is 100 tickets
        3,Whether there are multiple statements operating on shared data / shared variables yes

        All three conditions are met. It can be seen that the problem in our last case is a normal phenomenon, because it meets the above three conditions at the same time

        How to solve these problems?
        The first and second conditions cannot be changed. We can only find ways to change the third condition. As long as one of them is not satisfied, thread safety problems will not occur.

        Problem solving ideas:
            If there is a way to package the code of multiple statements operating shared data into a whole, it is OK if other threads cannot enter when one thread is executing.
            Until a thread executes the run method once, other threads can enter the execution.

        Java It provides a mechanism for us to use to solve the problem of thread safety: synchronous safety mechanism

        Solution 1: synchronize code blocks
        Statement format:
            Format:
              synchronized(Object) {code that needs to be synchronized;}
         1,What is the object here?
              Try creating any object
         2,What code needs to be synchronized?
              Code for multiple statements to operate on shared data
 */
public class SellTicketDemo4 {
    public static void main(String[] args) {
        //1. Create custom class object
        TicketWindow4 ticketWindow2 = new TicketWindow4();

        //2. Create three thread objects and simulate three windows
        Thread window1 = new Thread(ticketWindow2);
        Thread window2 = new Thread(ticketWindow2);
        Thread window3 = new Thread(ticketWindow2);

        //3. Name the thread object
        window1.setName("Window 1");
        window2.setName("Window 2");
        window3.setName("Window 3");

        //4. Start thread
        window1.start();
        window2.start();
        window3.start();
    }
}

Supplement:

Serialized stream:

Serialized stream
ObjectOutputStream
Deserialization stream
ObjectInputStream
Serialization operation problem
Why serialization?
How to implement serialization?
After serializing the data, modify the class file again, and there will be a problem reading the data. How to solve it?
Use the transient keyword to declare member variables that do not need to be serialized

Properties collection:

Use of Properties as a Map collection
Special features of Properties
public Object setProperty(String key,String value)
public String getProperty(String key)
public Set stringPropertyNames()
Combination of Properties and IO flow
public void load(Reader reader)
public void store(Writer writer,String comments)

Topics: Java Big Data