Assessment task of the ninth week of javaEE group = = main part: multi thread knowledge summary and related exercises==

Posted by reddymade on Sun, 06 Feb 2022 18:59:25 +0100

1, Concept questions

1. Briefly describe the relationship among programs, processes and threads. What is a multithreaded program?

Relationship between programs, processes and threads:

Program: a program is a set of ordered instructions and stored in a medium. It is a static concept.

Process: process is a concept introduced to enable programs to execute concurrently and to describe and control programs executed concurrently.

Before understanding the process, first describe the process entity. Process entity is composed of program segment, relevant data segment and PCB. It is a basic unit that can run independently, allocate resources independently and accept transfer independently.

Now let's explain the definition of a process: a process is an execution process of a process entity and an independent unit of the system for resource allocation and scheduling. It is a dynamic concept.

Thread: with the development of multiprocessor system, the requirement of improving the degree of concurrent execution of programs is higher and higher. In order to improve the concurrency of the system, the concept of thread is introduced. Thread is a smaller basic unit that can run independently than process (so it is also called "light process"), which better improves the degree of concurrent execution of program and gives full play to the advantages of multiprocessor.

Multithreaded program:

Multithreading: multiple tasks running simultaneously in the same process

For example, multithreaded download software can run multiple threads at the same time, but it is found that the results are inconsistent every time through the results of program running. Because multithreading has a characteristic: randomness. Cause: the CPU is constantly switching to deal with various threads in an instant, which can be understood as multiple threads scrambling for CPU resources.

2. What are the five basic states of a thread? How do they transform? Briefly describe the life cycle of threads.

Threads are always in one of the following five states from creation, running to end: new state, ready state, running state, blocking state and death state.

 

1. New state: when a thread is created with the new operator, such as new Thread(r), the thread has not started running, and the thread is in the new state. When a thread is in a new state, the program has not started running the code in the thread

2. Ready status (Runnable)

A newly created thread does not start running automatically. To execute the thread, you must call the thread's start() method. When the thread object calls the start() method, the thread is started. The start() method creates the system resources for the thread to run, and schedules the thread to run the run() method. When the start() method returns, the thread is ready.

The thread in the ready state does not necessarily run the run() method immediately. The thread must also compete with other threads for CPU time. Only when the CPU time is obtained can the thread run. Because in a single CPU computer system, it is impossible to run multiple threads at the same time, and only one thread is running at a time. Therefore, multiple threads may be ready at this time. Multiple threads in the ready state are scheduled by the thread scheduler of the Java runtime system.

3. Running status

When the thread obtains CPU time, it enters the running state and really starts to execute the run() method

  1. Blocked status

When a thread is running, it may enter the blocking state for various reasons: (1) the thread enters the sleep state by calling the sleep method; (2) the thread calls an operation blocked on I/O, that is, the operation will not return to its caller until the input / output operation is completed; (3) a thread attempts to obtain a lock that is being held by another thread; (4) the thread is waiting for a trigger condition;

The so-called blocking state is that the running thread has not finished running and temporarily gives up the CPU. At this time, other threads in the ready state can obtain CPU time and enter the running state.

  1. Dead state

There are two reasons for thread death: (1) the run method exits normally and dies naturally, (2) an uncapped exception terminates the run method and causes the thread to die suddenly. To determine whether the thread is currently alive (that is, it is either runnable or blocked), you need to use the isAlive method. If it is runnable or blocked, this method returns true; If the thread is still new and not runnable, or the thread dies, false is returned

3. What abstract methods are included in the runable interface? What are the main member variables and methods written in the Thread class?

Abstract methods included in the Runable interface:

The Runnable interface should be implemented by any class, and its instances will be executed by threads. This class must define a parameterless method called run()

The main member variables and methods in Thread class

Variable (attribute):

private static native void registerNatives();
    static {
        registerNatives();
    }
​
    private volatile String name;
    private int            priority;
    private Thread         threadQ;
    private long           eetop;
​
    /* Whether or not to single_step this thread. */
    private boolean     single_step;
​
    /* Whether or not the thread is a daemon thread. */
    private boolean     daemon = false;
​
    /* JVM state */
    private boolean     stillborn = false;
​
    /* What will be run. */
    private Runnable target;
​
    /* The group of this thread */
    private ThreadGroup group;
​
    /* The context ClassLoader for this thread */
    private ClassLoader contextClassLoader;
​
    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;
​
    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
​
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
​
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
​
    /*
     * The requested stack size for this thread, or 0 if the creator did
     * not specify a stack size.  It is up to the VM to do whatever it
     * likes with this number; some VMs will ignore it.
     */
    private long stackSize;
​
    /*
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;
​
    /*
     * Thread ID
     */
    private long tid;
​
    /* For generating thread ID */
    private static long threadSeqNumber;
​
    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */
​
    private volatile int threadStatus = 0;
  volatile Object parkBlocker;
​
   
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();
    //thread priority 
    public final static int MIN_PRIORITY = 1;
​
    public final static int NORM_PRIORITY = 5;
​
    public final static int MAX_PRIORITY = 10;
    public enum State {// Thread state
       
        NEW,
​
        RUNNABLE,
​
        BLOCKED,
​
        WAITING,
​
        TIMED_WAITING,
        
        TERMINATED;
    }

method:

(1) New thread:

Thread t1 = new Thread();
t1.start();

To create a new thread, you should call the start() method to start the thread; If you call the run() method directly, the method will also be executed, but it will be executed sequentially in the current thread as an ordinary method; If you use the start() method, a new thread will be created to execute the run() method.

(2) Thread interrupt:

public void interrupt();
public boolean isInterrupted();
public static boolean interrupted();

The three methods are very similar. Thread interrupt just notifies the target thread that someone wants you to exit, not causing the target thread to exit. The first method is to notify the target thread of interrupt, that is, to set the interrupt flag bit of the target thread; The second method determines whether the current thread is interrupted. If it is interrupted (i.e. the interrupt flag bit is set), it returns true; otherwise, it returns false; The third method judges the interrupt status of the current thread and clears the interrupt flag bit of the thread (that is, if the method is called twice in a row and the interrupt flag bit is not set again, false will be returned the second time because the interrupt flag bit has been cleared).

public static native void sleep(long millis) throws InterruptedException;

The sleep() method will sleep the current thread for several ms. if the interrupt() method is called during sleep, an InterruptedException exception will be thrown. As follows:

public class TestThread implements Runnable{
    @Override
    public void run() {
        while(true) {
            if(Thread.currentThread().isInterrupted()){ //Returns true if the interrupt flag bit has been set for the current thread
                System.out.println("Interrupted");
                break;
            }
​
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Interruted when sleep!");
                Thread.currentThread().interrupt(); //Thread. The sleep () method throws an exception due to an interrupt. At this time, it will clear the interrupt flag;
            }
​
            Thread.yield();
        }
    }
​
    public static void main(String[] args){
        Thread t1 = new Thread(new TestThread());
        t1.start();
​
        t1.interrupt(); //Set the interrupt flag bit of the target thread. The interrupt flag bit indicates that the current thread has been interrupted
    }
}

(3) Wait and notify:

public final void wait() throws InterruptedException;
public final native void notify();
public final native void notifyAll();

obj.wait() is to set the current thread to wait on this object until a thread calls obj notify() method (or notifyAll() method). When the wait () method is called, the thread will enter a waiting queue. There may be multiple threads in the waiting queue. Notify () will wake up one thread randomly, and notifyAll () will wake up all threads. The wait () and notify () methods must be called in the sychronized code block when calling these methods. First, a monitor of the target object is required. Then, when calling these methods, the monitor will be released. Unlike sleep, sleep() will always occupy the lock held, while wait () will release the lock.

(4) Join and yield

public final void join() throws InterruptedException;
public static native void yield();

If the execution of a thread requires the participation of another thread (for example, the current thread needs another thread to finish executing before it can continue executing), you can call the join () method at this time. t1. The join () method means to wait for thread T1 to finish executing, and then the current thread will continue executing. Of course, you can also set the time parameter for join (). Note: the essence of join() is to make the calling thread wait() on the current thread object instance. Some of its source codes are as follows:

while (isAlive()) {
   wait(0);
}

When the Thread is executed, it will let the waiting Thread call notifyAll() before exiting, and notify all waiting threads to continue executing. Therefore, do not use methods like wait() or notify() on Thread object instances. The yield() method is to make the current Thread give up the CPU, but the Thread will rob the CPU again.

4. The difference between start () method and run() method, and the similarities and differences between sleep() and wait()

The difference between the start() method and the run() method:

/**
 * Then why not cat run();  And? Because there is only the main thread, because cat run(); It's just a simple method. There are no other sub threads
 * Source code:
 *1.      public synchronized void start() {
 *               start0();
 *          }
 *          // start0(); It is a local method, which is called by the JVM, and the bottom layer is implemented in C/C + +
 *          // The real effect of multithreading is start0(), not run
 * 2.      private native void start0();
 */

Similarities and differences between sleep() and wait():

Firstly, sleep is to let the thread sleep and continue to execute after time. Wait is to wait and need to wake up before continuing to execute. In addition, sleep and wait are different in multithreading:

Usage: from the perspective of usage, sleep method is the method of Thread thread class, while wait is the method of Object top-level class. Sleep can be used anywhere, while wait can only be used in synchronization methods and synchronization blocks. CPU and lock resource release: after sleep and wait are called, the current Thread will be suspended and the CPU's execution time will be released. However, the difference is that sleep will not release the lock resources of the currently held Object and will continue to execute after time, while wait will release all locks and need to re obtain the Object resources after notify/notifyAll. Exception capture: sleep needs to capture or throw exceptions, while wait/notify/notifyAll does not.

5. How to implement multithreading in java programs? This paper briefly describes the similarities and differences between using Thread class and implementing Runnable interface.

A class can implement multithreading by inheriting the Thread class or implementing the Runnable interface

Experienced programmers will choose to implement Runnable interface for the following two main reasons:

First of all, java can only inherit by itself. Therefore, if you use the method of inheriting Thread, you may encounter problems in code refactoring in the future, because you can't inherit other classes.

Secondly, if a class inherits Thread, it is not suitable for resource sharing. However, if the Runable interface is implemented, it is easy to realize resource sharing.

Through the following examples, we can clearly see the difference between the two methods.

Inherit Thread class:

package test;
 
public class main1 {
	public static void main(String[] args) {
		testThread mTh1=new testThread("A");
		testThread mTh2=new testThread("B");
		mTh1.start();
		mTh2.start();
	}
}

class testThread extends Thread{
	private int count=5;
	private String name;
    public testThread(String name) {
       this.name=name;
    }
	public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "function  count= " + count--);
            try {
                sleep((int) Math.random() * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
	}
}

Implement Runnable interface:

package test;
 
public class main2 {
	public static void main(String[] args) {
		testRunnable mTh = new testRunnable();
	        new Thread(mTh, "C").start();//The same mTh, but not in the Thread. If the same instantiated object mt is used, an exception will occur   
	        new Thread(mTh, "D").start();
	        new Thread(mTh, "E").start();
	}
}

class testRunnable implements Runnable{
    private int count=15;
	@Override
	public void run() {
		  for (int i = 0; i < 5; i++) {
			  System.out.println(Thread.currentThread().getName() + "function  count= " + count--);
	            try {
	            	Thread.sleep((int) Math.random() * 10);
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        }
	}
	
}

6. Understand lambada expression (just understand)

2, Programming problem

  1. Use thread Sleep () writes a java program that counts down 10 seconds and outputs 10, 9, 8 1;

    public class ThreadTest01 {
        public static void main(String[] args) {
            for (int i=10;i>=1;i--){
                System.out.print(i+"\t");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    Running example:

     

  2. Use the Thread method and the Runnable interface method to create sub threads, and traverse natural numbers within 100

    Inherit Thread class:

public class ThreadTest02 {
    public static void main(String[] args) {
        Thread01 thread01 = new Thread01();
        thread01.start();
    }
}

class Thread01 extends Thread{

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

Running example:

 

Implement Runnable interface:

public class ThreadTest02 {
    public static void main(String[] args) {
        Runnable01 runnable01 = new Runnable01();
        Thread thread = new Thread(runnable01);
        thread.start();
    }
}

class Runnable01 implements Runnable{

    @Override
    public void run() {
        for (int i=1;i<=100;i++){
            System.out.print(i+" ");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Running example:

 

3. Three scalpers grab 200 tickets at the same time and print out which scalpers bought the first ticket

package xiancheng.JavaEETest;

public class ThreadTest03 {
    public static void main(String[] args) {
        Ticket ticket01 = new Ticket();
        ticket01.setName("Cattle one");
        Ticket ticket02 = new Ticket();
        ticket02.setName("Cattle two");
        Ticket ticket03 = new Ticket();
        ticket03.setName("Cattle three");
        // Open grab
        ticket01.start();
        ticket02.start();
        ticket03.start();
    }
}

class Ticket extends Thread{
    private static int count=200;
    private static boolean loop=true;

    @Override
    public void run() {
        while (loop){
            seel();
        }
    }

    public synchronized static void seel(){
        if (count<=0){// If there are no tickets
            System.out.println("Tickets are sold out!!!");
            loop=false;
        }
        else {// If there are still tickets, pause for 100 milliseconds
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"Grab the first place"+count+"Ticket,"+"surplus"+(--count)+"Ticket");
        }
    }
}

Running example:

 

4. Write A program to start three threads whose IDs are A, B and C respectively; Each thread prints its own ID value on the screen for 5 times. The printing order is ABCABC... Repeat three times

package xiancheng.JavaEETest;

public class ThreadTest04 {
    public static void main(String[] args) {
        for (int i=0;i<3;i++){
            TestID01 test1 = new TestID01();
            TestID02 test2 = new TestID02();
            TestID03 test3 = new TestID03();
            test1.setPriority(Thread.MAX_PRIORITY);
            test2.setPriority(Thread.NORM_PRIORITY);
            test3.setPriority(Thread.MIN_PRIORITY);
            test1.start();
            test2.start();
            test3.start();
            try {
                Thread.sleep(2500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("\n");
        }
    }
}

class TestID01 extends Thread{
    private int i=1;
    private char ID='A';
    @Override
    public void run() {
        while (i++<=5){
            System.out.print(ID);
            try {
                sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class TestID02 extends Thread{
    private int i=1;
    private char ID='B';
    @Override
    public void run() {
        while (i++<=5){
            System.out.print(ID);
            try {
                sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class TestID03 extends Thread{
    private int i=1;
    private char ID='C';
    @Override
    public void run() {
        while (i++<=5){
            System.out.print(ID);
            try {
                sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Running example:

 

3, Challenge questions

Make a countdown timer for a given time, pause for 1 second between each number, and output a string every 10 numbers

package xiancheng.JavaEETest;

import java.util.ArrayList;

public class ThreadTest05 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("javaEE");
        list.add("jact");
        list.add("Php");
        list.add("tom.class");
        list.add("Winter Olympics");
        Time time = new Time(list);
        time.start();
    }
}

@SuppressWarnings({"all"})
class Time extends Thread{
    private int time =50;
    private ArrayList<String> list =null;

    public Time(ArrayList<String> list ){
        this.list=list;
    }
    @Override
    public void run() {
        int i=0;
        while (time>=0){
            time--;
            i++;
            if (i==10){
                System.out.println(list.get(time/10));
                i=0;
            }
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Running example:

 

Topics: Java JavaEE architecture