Educoder/Touge JAVA——Advanced Features of JAVA: Multithreading Basics (2) Common Functions

Level 1: Thread status and scheduling

related information

Thread state and scheduling

If you understand the picture below, your understanding of threads will be improved.

  1. When we use newkeywords to create a new thread, the thread enters the newly created state ( New), which is the unstarted state in the figure;

  2. Call startthe method to start the thread, and at this time it enters the runnable state, that is, the ready state ( Runnable);

  3. The ready state acquires CPU resources, starts to execute runthe method, and enters the running state ( Running);

  4. Blocked state ( Blocked): The blocked state means that the thread gives up the right to use the CPU for some reason and temporarily stops running. Until the thread enters the ready state, it has the opportunity to go to the running state. There are three types of blocking:

    • Waiting for blocking: The running thread executes wait()the method, and the JVM will put the thread into the waiting pool. ( waitwill release the lock held);

    • Synchronous blocking: When the running thread acquires the synchronization lock of the object, if the synchronization lock is occupied by other threads, the JVM will put the thread into the lock pool;

    • Other blocking: When a running thread executes a method sleep()or join()an I/O request is issued, the JVM will put the thread in a blocked state. When sleep()the state times out, join()the waiting thread terminates or times out, or the I/O processing is completed, the thread re-transfers to the ready state. (Note that sleepthe held lock will not be released);

  5. Dead state ( ): The thread ends its life cycle Deadwhen the thread finishes executing or exits the method due to an exception .run()

thread priority

We know that the execution of multiple threads is random, and which thread is executed in a certain period of time depends on which thread has the CPUexecution permission at this time.

In Javathe medium thread has priority, and the thread with high priority will get more running opportunities.

JavaThe priority of the thread is represented by an integer, and the value range is 1~10. ThreadThe class has the following three static constants:

  1. static int MAX_PRIORITY
  2. 线程可以具有的最高优先级,取值为10。
  3. static int MIN_PRIORITY
  4. 线程可以具有的最低优先级,取值为1。
  5. static int NORM_PRIORITY
  6. 分配给线程的默认优先级,取值为5。

If you want to set and get the thread's priority, you can use Threadthe class's setPriority()and getPriority()methods.

Each thread has a default priority. The default priority of the main thread is Thread.NORM_PRIORITY.

The priority of a thread has an inheritance relationship. For example, if a thread Ais created in a thread B, Bit will Ahave the same priority as the thread.

The JVM provides 10several thread priorities, but none of them map well with common operating systems. If you want the program to be ported to various operating systems, you should only use Threadthe following three static constants as priorities, so as to ensure that the same priority uses the same scheduling method.

You also need to know about thread scheduling and priority:

  1. ThreadSleep : Thread.sleep(long millis)Method that makes a thread go to a blocked state. millisThe parameter sets the time to sleep, in milliseconds. When the sleep is over, it turns to the ready ( Runnable) state. sleep()Platform portability is good.

  2. Thread wait : A method Objectin a class wait()that causes the current thread to wait until other threads call the object's notify()method or notifyAll()wakeup method. These two wake-up methods are also Objectmethods in the class, and the behavior is equivalent to calling wait(0).

  3. Thread concession : Thread.yield()method, suspend the currently executing thread object, and give the execution opportunity to the same or higher priority thread.

  4. ThreadJoin : join()method, waits for other threads to terminate. If the method of another thread is called in the current thread join(), the current thread will enter the blocking state until the other process finishes running, and then the current thread will change from blocking to ready state.

  5. thread wakeup : method Objectin the class notify()that wakes up a single thread waiting on this object's monitor. If all threads are waiting on this object, one of the threads will be chosen to wake up. The choice is arbitrary and occurs when the decision on the implementation is made. A thread waits on an object's monitor by calling one of its waitmethods . The awakened thread cannot continue executing until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual way with all other threads actively synchronizing on this object; for example, the awakened thread has no reliable privilege or disadvantage in being the next thread to lock on this object. There is another similar method notifyAll(), which wakes up all threads waiting on this object monitor.

programming requirements

slightly.

 Level 2: Common functions (1)

related information

sleep() function

sleep(long millis): Sleeps (pauses execution) the currently executing thread for the specified number of milliseconds.

The way of use is very simple and can be used inside the thread Thread.sleep(millis).

sleep()Make the current thread enter a stagnant state (block the current thread) and give up the use of the CPU. The purpose is to prevent the current thread from occupying the CPU resources obtained by the process alone, so as to leave a certain period of time for other threads to execute;

The thread does not necessarily execute immediately after sleep()the sleep time expires, because other threads may be running and not scheduled to give up execution, unless this thread has a higher priority.

join() function

joinThe definition of the function means: wait for the thread to terminate .

When we run the thread, we may encounter the situation that when the sub-thread is run in the main thread, the main thread needs to obtain the final execution result of the sub-thread.

But in many cases, the sub-threads perform a lot of time-consuming operations, and the main thread often ends before the sub-threads. At this time, the main thread cannot obtain the final execution results of the sub-threads.

Use joinfunctions to solve this problem.

Let's understand with two examples:

Version without joinfunction:

class MyThread extends Thread {
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    public void run() {
        System.out.println("子线程开始运行");
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程" + name + "运行" + i);
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackT\frace();
            }
        }
        System.out.println("子线程结束");
    }
}
public class Test {
    public static void main(String[] args) {
        Thread t = new MyThread("子线程A");
        t.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行" + i);
        }
        System.out.println("主线程结束");
    }
}
/**************************/
输出结果(每次都不一样):
主线程执行0
主线程执行1
主线程执行2
主线程执行3
主线程执行4
主线程结束
子线程开始运行
子线程子线程A运行0
子线程子线程A运行1
子线程子线程A运行2
子线程子线程A运行3
子线程子线程A运行4
子线程结束

It can be found that every time it runs, the main thread ends before the child thread.

Use joinfunction:

package step1;
class MyThread extends Thread {
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    public void run() {
        System.out.println("子线程开始运行");
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程" + name + "运行" + i);
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackT\frace();
            }
        }
        System.out.println("子线程结束");
    }
}
public class Test {
    public static void main(String[] args) {
        Thread t = new MyThread("子线程A");
        t.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行" + i);
        }
        try {
            t.join();
        } catch (Exception e) {
            e.printStackT\frace();
        }
        System.out.println("主线程结束");
    }
}
/****************************************************/
输出结果:
主线程执行0
主线程执行1
主线程执行2
主线程执行3
子线程开始运行
主线程执行4
子线程子线程A运行0
子线程子线程A运行1
子线程子线程A运行2
子线程子线程A运行3
子线程子线程A运行4
子线程结束
主线程结束

It can be found that no matter how many times it runs, the main thread will wait for the child thread to end before ending.

programming requirements

Begin - EndPlease read the code on the right carefully, and supplement the code in the area according to the prompts in the method . The specific tasks are as follows:

  • Create a custom thread to realize numthe value of the first Fibonacci sequence numfrom 0the beginning, and mainobtain the final calculation result of the sub-thread in the function.
package step2;

import java.util.Scanner;

public class Task {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		//请在此添加实现代码
     /********** Begin **********/
     Thread t=new MyThread("子线程",num);
     t.start();
    /********** End **********/		
	}
}
		//请在此添加实现代码
   /********** Begin **********/
class MyThread extends Thread {
    private String name;
    private int num;
    public MyThread(String n,int m){
        this.name=n;
        this.num=m;
    }
    public void run(){
        int a=1;
        int b=1;
        if(num==1|num==2){
            System.out.println("子线程计算结果为:"+b);
        }
        for(int i=0;i<num-2;i++){
            int t=a;
            a=b;
            b=t+a;
        }
        System.out.println("子线程计算结果为:"+b);
    }	
}
   /********** End **********/

Level 3: Common Functions (2)

related information

yield function

yieldFunction can be understood as "concession", its role is: suspend the currently executing thread object, and execute other threads.

yield()What should be done is to return the currently running thread to a runnable state to allow other threads of the same priority to get a chance to run. Therefore, the purpose of use yield()的is to allow appropriate round-robin execution between threads of the same priority . However, in practice, there is no guarantee yield()that the purpose of yielding will be achieved, because the yielding thread may be selected again by the thread scheduler.

Example:

public class Task {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
        MyThread mTh1=new MyThread("A");
        MyThread mTh2=new MyThread("B");
        mTh1.start();
        mTh2.start();
        System.out.println(Thread.currentThread().getName()+ "主线程运行结束!");
    }
}
class MyThread extends Thread  {
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println(name + "线程" + "执行" + i);
            if(i  == 10){
                this.yield();
            }
        }
    }
}
/************************************************************************/
运行结果有两种情况:

第一种情况:A(线程)当执行到10时会让掉CPU时间,这时B(线程)抢到CPU时间并执行。

第二种情况:B(线程)当执行到10时会让掉CPU时间,这时A(线程)抢到CPU时间并执行。

We can also consider adding setPrioritya function to change the priority of the thread to change the execution order of the thread.

wait function

To understand waitfunctions we first need to understand the concept of thread locks . Thread lock: In fact, it is like the lock in our daily life. If a house is locked, others cannot get in. It is similar in Java. If a piece of code acquires a lock, then other places cannot run this code. Can wait for the lock to be released.

Here we will involve two functions, 1. wait(), 2. notify(). These two functions are Objectfunctions that come with the class.

In the following example, we will use it synchronized(Obj)to achieve thread synchronization. The concept of synchronization will be mentioned later. It doesn't matter if you don't understand it here, and it will not affect your waitunderstanding of functions.

Functionally speaking:

  • wait()That is to say, after the thread acquires the object lock, it actively releases the object lock, and the thread sleeps at the same time. Until another thread calls the object to notify()wake up the thread, it can continue to acquire the object lock and continue to execute;

  • The corresponding notify()is the wake-up operation of the object lock.

But one thing to note is that after the call, the object lock is not released immediately, but after the execution of the notify()corresponding statement block is completed, after the lock is automatically released, the JVM will randomly select a thread from the object-locked threads and give it the object lock. lock, wake up the thread, and continue execution. This provides synchronization and wake-up operations between threads.synchronized(){}wait()

Thread.sleep()Both Object.wait()of them can suspend the current thread and release the control of the CPU. The main difference is that Object.wait()the control of the object lock is released at the same time as the CPU is released.

What is learned on paper is superficial. If you want to know this, you have to do it yourself. We still learn the usage of these functions through examples.

Question: Create two threads, A thread prints 5times A, B thread prints 5times B, the threads are required to run at the same time, and print 5times alternately AB.

This problem can be Objectsolved easily. code show as below:wait()notify()

public class MyThread implements Runnable {   
    private String name;   
    private Object prev;   
    private Object self;   
    private MyThread(String name, Object prev, Object self) {   
        this.name = name;   
        this.prev = prev;   
        this.self = self;   
    }   
    public void run() {   
        int count = 5;   
        while (count > 0) {   
            synchronized (prev) {   
                synchronized (self) {   
                    System.out.print(name);   
                    count--;  
                    self.notify();   
                }   
                try {   
                    prev.wait();   
                } catch (InterruptedException e) {   
                    e.printStackT\frace();   
                }   
            }   
        }  
        System.exit(0);//退出jvm
    }   
    public static void main(String[] args) throws Exception {   
        Object a = new Object();   
        Object b = new Object();   
        MyThread ta = new MyThread("A", b, a);   
        MyThread tb = new MyThread("B", a, b);   
        new Thread(ta).start();
        Thread.sleep(100);  //确保按顺序A、B执行
        new Thread(tb).start();
        Thread.sleep(100);  
        }   
}
/********************************************************************/
运行程序,结果为:

ABABABABAB

Summary of common thread functions

The following table lists the commonly used functions of the thread class:

function describe
public void start() Causes the thread to begin executing; the Java virtual machine calls the thread's run method.
public void run() If the thread was constructed using an independent Runnable run object, the Runnable object's run method is invoked; otherwise, the method does nothing and returns.
public final void setName(String name) Change the thread name to be the same as the parameter name.
public final void setPriority(int priority) Change the priority of a thread.
public final void setDaemon(boolean on) Mark the thread as a daemon or user thread.
public final void join(long millisec) The maximum time to wait for this thread to terminate is millis milliseconds
public void interrupt() Interrupt thread.
public final boolean isAlive() Tests whether the thread is alive.
public static void yield() Suspends the currently executing thread object and executes other threads.
public static void sleep(long millisec) Sleeps (pauses execution) the currently executing thread for the specified number of milliseconds, subject to the precision and accuracy of system timers and the scheduler.
public static boolean holdsLock(Object x) Returns true if and only if the current thread holds the monitor lock on the specified object.
public static Thread currentThread() Returns a reference to the currently executing thread object.
public static void dumpStack() Print the current thread's stack trace to the standard error stream.

programming requirements

Begin - EndPlease read the code on the right carefully, and supplement the code in the area according to the prompts in the method . The specific tasks are as follows:

  • Create three threads, Athread print 5times E, thread B print 5times D, Cthread print 5times U, require threads to run at the same time, print 5times alternately EDU.
package step3;
public class MyThread implements Runnable {   
//请在此添加实现代码
/********** Begin **********/
    private String name;
	private Object prev;
	private Object self;
	private MyThread(String name,Object prev,Object self){
		this.name = name;
		this.prev = prev;
		this.self = self;
	}
	public void run(){
		int count = 5;
		while(count>0){
			synchronized(prev){
				synchronized(self){
					System.out.print(name);
					count--;
					self.notify();
				}
				try {
                    prev.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
				}
			}
		}
		System.exit(0);
	}
 	public static void main(String[] args) throws Exception {   
        Object a = new Object();
        Object b = new Object();
        Object c = new Object();
		MyThread ta = new MyThread("E",c,a);
		MyThread tb = new MyThread("D",a,b);
		MyThread tc = new MyThread("U",b,c);
		new Thread(ta).start();
		Thread.sleep(10);
		new Thread(tb).start();
		Thread.sleep(10);
		new Thread(tc).start();
		Thread.sleep(10);
    }   
/********** End **********/  
}

Guess you like

Origin blog.csdn.net/zhou2622/article/details/128382518