Threads for learning notes

Multithreaded

1. Implement multithreading

process

Is a running program

  • Is the system's independent unit for resource allocation and invocation
  • Each process has its own memory space and system resources
thread

Is a single sequential control flow in a process and is an execution path

  • Single-threaded: A process with only one execution path is called a single-threaded program
  • Multithreaded: A process is called a multithreaded program if it has multiple execution paths
Implement multithreading:
  1. Inherit Thread Class
    • Define a class MyThread inherits the Thread class
    • Override run() method in MyThread class
    • Create an object of the MyThread class
    • Start Thread

Note: run() encapsulates code executed by a thread.
run(): Encapsulates code executed by a thread, making a direct call, which is equivalent to a call to a common method.
strat(): Starts the thread; then a JVM calls the thread's run() method.

Method in the Thread class: Set and get the thread name

  • void setName(String name): Change the name of this thread to the parameter name
  • It can also be set by a construction method
  • String getName(): Returns the name of this thread
  • Public static Thread current Thread(): Returns a reference to the currently executing thread object
public class MyThread extends Thread {
    MyThread(){}
    MyThread(String name){
        super(name);
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            System.out.println(getName()+","+i);
        }
    }
}


public class MyThreadDemo {
    public static void main(String[] args) {

        //Set the thread name through the set method

//        MyThread mt = new MyThread();
//        MyThread mt2 = new MyThread();
//
//        mt.setName("A: ");
//        mt2.setName("B: ");
//// mt.run(); //direct call
////        mt2.run();
//        mt.start();
//        mt2.start(); //Start the thread, JVM calls the run method

        //Set by construction method:
        MyThread mt = new MyThread("A:");
        MyThread mt2 = new MyThread("B:");
        mt.start();
        mt2.start();

        //Static Thread current Thread() returns a reference to the currently executing thread object
        System.out.println(Thread.currentThread().getName());    // main
    }
}
Thread Scheduling

Two threading scheduling models:

  • Time-sharing scheduling model: All threads take turns using CPU usage, evenly allocating each thread's CPU time slice.
  • Preemptive scheduling model: Give priority to high priority threads using CPUs.If the threads have the same priority, they will randomly choose one, and the threads with higher priority will get more CPU time slices.(java).

Method of setting and getting thread priority in Thread class

  • public final int getPriority(): Returns the priority of this thread.
  • Public final void setPriority: Change the priority of this thread (thread priority range is 1-10, default is 5).

A higher thread priority simply means that the thread has a higher chance of getting CPU time slices, but it needs to run more times or multiple times to see what you want.

public class ThreadPriority extends Thread{
    ThreadPriority(){}
    ThreadPriority(String name){
        super(name);
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            System.out.println(getName()+":"+i);
        }
    }
}


public class Demo {
    public static void main(String[] args) {
        ThreadPriority tp = new ThreadPriority("A:");
        ThreadPriority tp2 = new ThreadPriority("B:");
        ThreadPriority tp3 = new ThreadPriority("C:");

        System.out.println(Thread.MIN_PRIORITY);//1
        System.out.println(Thread.NORM_PRIORITY);//5
        System.out.println(Thread.MAX_PRIORITY); // 10
        System.out.println("--------------------------------");
        System.out.println(tp.getPriority());//5
        System.out.println(tp2.getPriority());//5
        System.out.println(tp3.getPriority());//5

        System.out.println("-------------------------");
        //set priority
        //Public final void setPriority: Change the priority of this thread

        tp.setPriority(5);
        tp2.setPriority(10);
        tp3.setPriority(1);

        System.out.println(tp.getPriority());//5
        System.out.println(tp2.getPriority());//10
        System.out.println(tp3.getPriority());//1

        System.out.println("-------------------");
        tp.start();
        tp2.start();
        tp3.start();
    }
}
Thread Control

Method:

  • static void sleep(long millis): The number of milliseconds specified to hold (pause) the currently executing thread
  • void join(): Wait for this thread to die
  • The void setDaemon(boolean on) marks this thread as a daemon thread, and the JAVA virtual machine exits when the running thread is a daemon thread
sleep
public class Sleep extends Thread{
    Sleep(){}
    Sleep(String name){
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            System.out.println(getName()+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


public class SleepDemo {
    public static void main(String[] args) {
        Sleep s = new Sleep("A");
        Sleep s2 = new Sleep("B");
        Sleep s3 = new Sleep("C");

        s.start();
        s2.start();
        s3.start();
    }
}
join
public class JoinDemo {
    public static void main(String[] args) {

        //Yong Zheng, Xue is the son of Kangxi.YUNZHENG AND YOU want to inherit the throne and abrogate Kangxi
//        void join(): Wait for this thread to die-->Kangxi
        Join j = new Join("Kangxi");
        Join j2 = new Join("Yongzheng");
        Join j3 = new Join("Tumble");

        j.start();
        try {
            j.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        j2.start();
        j3.start();
    }
}


public class Join extends Thread{
    Join(){}
    Join(String name){
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            System.out.println(getName()+i);
        }
    }
}
setDaemon
public class SetDaemon extends Thread{
    public SetDaemon() {
    }

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

    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            System.out.println(getName()+i);
        }
    }
}


public class SetDaemonDemo {
    public static void main(String[] args) {

        //Brothers who worship died on the same day in the same year
        SetDaemon sd2 = new SetDaemon("False Bamboo");
        SetDaemon sd3 = new SetDaemon("Duan Yu");

        //Set as Main Thread
        Thread.currentThread().setName("Look crazy");
        //Set as Daemon Thread
        sd2.setDaemon(true);
        sd3.setDaemon(true);

        sd2.start();
        sd3.start();

        for (int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName()+i);
        }

    }
}
Thread life cycle

Implement the Runnable interface for multithreading
  • Define a class MyRunnable to implement the Runnable interface
  • Implement the run() method in the MyRunnable class
  • Create an object of the MyRunnable class
  • Create an object of the Thread class with the MyRunnable object as a parameter to the construction method
  • Start Thread

Two ways of multithreading:

  1. Inherit Thread Class
  2. Implement Runnable Interface

Implement Runnable interface: Avoid the limitation of single inheritance of Java, suit the case that multiple codes of the same program handle the same resource, effectively separate the code and data of thread and program, better reflect the object-oriented design idea

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


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

        //Create an object of the Thread class with the MyRunnable object as a parameter to the construction method
        Thread t1 = new Thread(mr,"A");
        Thread t2 = new Thread(mr,"B");

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

    }
}

Thread Synchronization

Ticket Selling
public class SellTicket implements Runnable {
    private int Ticket = 100;

    @Override
    public void run() {
        while (true) {
            if (Ticket > 0) {
                try {
                    Thread.sleep(100); //Simulate ticket selling interval
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "Sales No." + Ticket + "Tickets");
                Ticket--;

            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        SellTicket st = new SellTicket();

        Thread t = new Thread(st, "Window 1:");
        Thread t2 = new Thread(st, "Window 2");
        Thread t3 = new Thread(st, "Window 3");

        t.start();
        t2.start();
        t3.start();
    }
}

Because of the randomness of thread execution

  • Heavy votes appear
  • Negative votes appear
Solve

Criteria for determining whether multithreaded programs have data security issues

  • Is it a multithreaded environment
  • Is there shared data
  • Is there more than one statement to operate on shared data
Solution ideas
  • Destroy the safe environment
    Realization:
  • Lock code for multiple statement operations that share data so that only one thread can execute at any time (synchronize code blocks)
  • Format:
Synchronized (any object){
    Code for sharing data with multiple statements
}
public class SellTicket implements Runnable {
    private int Ticket = 100;
    private Object obj = new Object();

    @Override
    public void run() {
        synchronized (obj) {
            while (true){
                if (Ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "Window is selling #" + Ticket + "Tickets");
                    Ticket--;
                }
            }
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st = new SellTicket();

        Thread t = new Thread(st, "No.1");
        Thread t2 = new Thread(st, "No.2");
        Thread t3 = new Thread(st, "No.3");

        t.start();
        t2.start();
        t3.start();
    }
}

Advantages and disadvantages:

  • Solved multithreaded security issues
  • When there are many threads, because each thread determines the lock on synchronization, this is resource intensive and reduces the efficiency of the program
Synchronization method

Synchronization method: Add the synchronized keyword to the method

  • Format:
    Modifier synchronized return value type method name (parameter)
    Lock object for synchronization method:
  • this
public class SellTicket implements Runnable {
    private int Ticket = 100;
    private int x = 0;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {

                if (Ticket > 100) {
                    if (x % 2 == 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "Window is selling #" + Ticket + "Tickets");
                        Ticket--;
                    } else {
                        sellTicket();
                    }
                    x++;
                }
            }

        }
    }

    private synchronized void sellTicket() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "Window is selling #" + Ticket + "Tickets");
        Ticket--;
    }
}

Synchronize static methods: that is, add the synchonized keyword to the static method

  • Format:
    • Modifier static synchronized return value type method name (method parameter) {}
      Lock object for synchronous static methods
  • Class name+class

Thread-safe Classes

  1. StringBuffer
    • If you want to manipulate a small amount of data with= String
    • Single Thread Operation String Buffer Operating Lots of Data= StringBuilder
    • Multithreaded Operation String Buffer Operating Lots of Data
  2. Vector
    • Vectors, like ArrayLists, are also implemented through arrays, except that they support thread synchronization, where only one thread can write Vectors at a given time, avoiding inconsistencies caused by multiple threads writing at the same time, but synchronization is expensive and therefore slower to access than ArrayLists.
  3. Hashtable
    A synchronized List (List List) in the Collections class can return a thread-safe list, a synchronized Map (Map<K, V> m) can return a thread-safe map,...
Lock lock (after JDK5)
  1. Lock implementations provide more extensive locking operations than using synchronized methods and statements
  • Lock provides methods for acquiring and releasing locks
    • void lock(): Get a lock
    • void unlock(): release lock
  1. Lock is an interface that cannot be instantiated directly. It is instantiated here using the class ReentrantLock it implements
  • Construction method of ReentrantLock
    • ReentrantLock(): Create an instance of ReentrantLock
mport java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements Runnable{
    private int Ticket = 100;
    private Lock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            try {
                lock.lock();
                if (Ticket > 0){
                    System.out.println(Thread.currentThread().getName()+"Window is selling #"+Ticket+"Tickets");
                    Ticket--;
                }
            }finally { //Use finally to ensure lock must be released
                lock.unlock();
            }
        }
    }
}

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st = new SellTicket();

        Thread t = new Thread(st, "No.1");
        Thread t2 = new Thread(st, "No.2");
        Thread t3 = new Thread(st, "No.3");

        t.start();
        t2.start();
        t3.start();
    }
}

bounded-buffer problem

  1. The producer-consumer problem actually consists of two main types of threads:
  • One is the producer thread used to produce data
  • One is consumer threads for consuming data
  1. To decouple the relationship between producers and consumers, a shared data area is often used, like a warehouse.
  • Producer production data is then placed directly in shared data without concern for consumer behavior
  • Consumers only need to get data from the shared data area, not the producer's behavior.

Producer --->Shared Data Area <----- Consumer

  1. To reflect the production and consumption process of waiting and waking up, java provides several methods for us to use, these methods in the Object class of waiting and waking up methods:
  • void wait() causes the current thread to wait until another thread calls the notify() or notifyAll() methods of the object
  • void notify() wakes up a single thread waiting for the object monitor
  • void notifyAll() wakes up all threads waiting for object monitors
/*
Producer-consumer case:
A milk bo x defines a member variable that represents the Xth bottle of milk and provides operations to store and obtain milk
 Producer: Implements the Runnable interface, implements the run() method, and invokes the operation to store milk
 Customer: Implement the Runnable interface, implement the run() method, and call the get milk operation '
Test class (Demo): contains the main method, which has the following code steps:
    1.Create a milk box object, which is a shared data area
    2.Create a producer object and pass the milk box object as a construction method parameter because the store milk operation is invoked in this class
    3.Create a consumer object and pass the milk box object as a construction method parameter because the store milk operation is invoked in this class
    4.Create two threaded objects, passing producer and consumer objects as construction method parameters, respectively
    5.Start Thread
 */

 public class Box {
    private int milk;
    private boolean x = false;//Status of milk carton, no milk

    public synchronized void put(int mike){
        //If there is milk waiting to be consumed
        if (x){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.milk = mike;
        System.out.println("Employee placement"+milk+"Bottled milk");
        x = true;
        notify();
    }

    public synchronized void get(){
        //If there is no milk to wait for
        if (!x){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("User gets"+milk+"Bottled milk");
        x = false;
        notify();
    }
}

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

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

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

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


public class Demo {
    public static void main(String[] args) {
        Box b = new Box();
        Producer p = new Producer(b);
        Customer c = new Customer(b);

        Thread t = new Thread(p);
        Thread t2 = new Thread(c);

        t.start();
        t2.start();
    }
}

Tags: Java jvm

Posted on Mon, 18 May 2020 12:46:16 -0400 by matt_4013