In the last article, we introduced the constructors for Thread, but the constructors alone are not enough. We need to learn more about the apis commonly used by the class. This will give us a deeper understanding of the class and give us more options.

There are dozens of apis provided by the Thread class. Due to space problems, this article will only select a few representative ones to explain. The rest of the API partners interested can be viewed through the source code, can also give me a message, we discuss and learn together.

The target

  1. currentThread
  2. setPriority
  3. yield
  4. sleep
  5. interrupt
  6. interrupted
  7. join

content

1. currentThread

This method is used to return a reference to the current thread of execution, and we can use it to get the current thread object in a block of code. Although it may seem simple, it is widely used and will be used extensively in the future.

Methods:

public static native Thread currentThread(a);
Copy the code

Code:

/** * this example shows that thread.currentThread () has its own Thread reference object. * /
public class CurrentThreadDemo {
    public static void main(String[] args) {
        // Print the result: true
        Thread t = new Thread(() -> {
            System.out.println("t".equals(Thread.currentThread().getName()));
        }, "t");
        t.start();
        // Print the result: true
        System.out.println("main".equals(Thread.currentThread().getName())); }}Copy the code

2. setPriority

Processes have priorities, and so do threads. In theory, higher-priority threads are scheduled by the CPU first, but this is not always the case.

If the CPU is busy, you may get more CPU time slices by setting the priority, but when the CPU is idle, setting the priority has almost no effect. Therefore, let’s not try to use priorities in programming to bind certain businesses or make businesses depend on priorities, which may produce results that are not consistent with what you expect.

Methods:

public final void setPriority(int newPriority);	// Set thread priority
public final int getPriority(a);	// Get the thread priority
Copy the code

Case study:

/ * * * t1 thread priority is lower than that of the t2 thread, normally should statistical number is less than the thread t2 * but I'm here to the number of random test statistics for: * t1:59573 * t2: 34321 * Different CPU resources will have different results, you can test several times to see */
public class PriorityDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (true) {
                System.out.println("t1"); }},"t1");
        Thread t2 = new Thread(() -> {
            while (true) {
                System.out.println("t2"); }},"t2");
		// The minimum value is 1, the median value is 5, and the maximum value is 10
        t1.setPriority(9);
        t2.setPriority(10); t1.start(); t2.start(); }}Copy the code

3. yield

The yield method is a heuristic that tells the scheduler that the current thread is willing to give up its current use of the processor. The scheduler is free to ignore this prompt. Its use should be combined with detailed performance analysis and benchmarking to ensure that it actually has the desired effect.

This method is rarely used. It can be useful for debugging or testing purposes, as it may help to reproduce errors caused by race conditions.

Methods:

public static native void yield(a);
Copy the code

Case study:

/** * If you leave the comments out, you can see that the console output is sometimes 0 and sometimes 1 *. If you comment out the comments, you can see that the console output is always 0 */
public class YieldDemo {
    public static void main(String[] args) {
        IntStream.range(0.2).mapToObj(YieldDemo::test).forEach(Thread::start);
    }

    private static Thread test(int index){
        return new Thread(() -> {
            // if (index == 0){
            // Thread.yield();
            // }System.out.println(index); }); }}Copy the code

4. sleep

Sleep is a static method that puts the currently executing thread into hibernation (temporarily stopping execution) for a specified number of milliseconds, depending on the accuracy and accuracy of the system timer and scheduler. The thread does not lose ownership of any monitors (such as monitor locks, more on which in a future article).

Methods:

public static native void sleep(long millis);	// The number of milliseconds to sleep
public static void sleep(long millis, int nanos);	// The number of milliseconds and nanoseconds to sleep
Copy the code

Case study:

/** * In this example, we sleep the custom Thread and the main Thread separately. Each Thread's sleep does not affect each other * thread.sleep () only causes the current Thread to sleep for the specified time */
public class SleepDemo {
    public static void main(String[] args) {
        new Thread(() -> {
            long startTime = System.currentTimeMillis();
            sleep(2000);
            System.out.printf("%s thread time: %d%s", Thread.currentThread().getName(), System.currentTimeMillis() - startTime, "ms");
            System.out.println("");
        }, "t").start();

        long startTime = System.currentTimeMillis();
        sleep(3000);
        System.out.printf("%s thread time: %d%s", Thread.currentThread().getName(), System.currentTimeMillis() - startTime, "ms");
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code

The difference between yield and sleep:

  • Yield is just a tip to the CPU scheduler, which, if valid, results in a thread context switch;
  • Sleep causes the current thread to pause for a specified period of time, with no CPU time slice consumed;
  • Yield causes the thread to move from the RUNNING state to the RUNNABLE state.
  • Sleep causes a thread to block briefly and then release CPU resources for a given amount of time.
  • Yield is not guaranteed to be effective, while sleep is almost 100% used to sleep at the specified time (the final sleep time depends on the accuracy of the system’s timer and scheduler).
  • Yield cannot catch interrupt signals, whereas sleep can if interrupted by another thread

5. interrupt

Thread Interrupt is a very important API and a frequently used method. When calling:

  1. Wait (), wait (long), or wait (long, int) or join (), join (long), join (long, int) methods of class Object block this thread. Then the interrupted status is cleared and InterruptedException is received.

  2. InterruptibleChannel I/O operations, the channel will be shut down, the thread of the interrupted status will be set, and this thread will receive Java. Nio. Channels. ClosedByInterruptException.

  3. The Selector’s wakeup method sets the thread’s interrupted state, and it will immediately return from the selection operation (which may have a non-zero value), just as the Selector’s wakeup method is called.

There are several apis related to this.

Methods:

public void interrupt(a);	// Interrupt blocking
public static boolean interrupted(a);	// Determine whether the current thread is interrupted. This method will erase the thread's identity directly
public boolean isInterrupted(a);	// Determine whether the current thread is interrupted
// Both the interrupted and isInterrupted methods are implemented by calling the local method isInterrupted(), where the ClearInterrupted parameter is used to control whether or not the thread interrupt is erased. Once the identifier is erased, all subsequent judgments will be false
private native boolean isInterrupted(boolean ClearInterrupted);
Copy the code

Case study:

/** * Create thread T and sleep for 1 minute ** After the main thread sleep for 2 seconds, interrupt thread T. Console output: interrupt, program end */
public class InterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {
                System.out.println("interrupt"); }},"t");
        t.start();

        Thread.sleep(2000); t.interrupt(); }}Copy the code

There is an interrupt flag inside the thread. If a thread is being interrupted, its flag is set, as described in the source code.

public void interrupt(a) {
    if (this! = Thread.currentThread()) checkAccess();synchronized (blockerLock) {
        Interruptible b = blocker;
        if(b ! =null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}
Copy the code

However, if the interrupt method is called while the current thread is executing an interruptible method and it is blocked, the flag will become clear. This will be explained in more detail in a later article.

7. join

The join method of Thread is also a very important method, which can be used to achieve a lot of strong functions. There are three different methods in the Thread class, as follows:

Methods:

public final void join(a);	// Wait permanently for the end of the thread lifecycle
public final synchronized void join(long millis);	// Set the maximum number of milliseconds to wait
public final synchronized void join(long millis, int nanos); // Set the maximum wait in milliseconds and nanoseconds. 0 indicates a permanent wait
Copy the code

Case study:

/** * Create two threads 1 and 2 and start them separately to output in the console. * At the same time, the main thread calls the methods of both threads, and you will notice that threads 1 and 2 will output alternately until both threads are finished. * At this point, the main thread will loop output, and if the join method is commented out, all three threads will output at the same time
public class JoinDemo {
    public static void main(String[] args) throws InterruptedException {
        List<Thread> list = IntStream.range(1.3).mapToObj(JoinDemo::getThread).collect(Collectors.toList());

        list.forEach(Thread::start);

        for (Thread thread : list) {
            thread.join();
        }

        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-" + i);
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) { e.printStackTrace(); }}}private static Thread getThread(int name){
        return new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "-" + i);
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException e) { e.printStackTrace(); } } }, String.valueOf(name)); }}Copy the code

conclusion

In this article, we’ve looked at some of Thread’s more common apis, which are essential to mastering highly concurrent programming!

This is the end of today’s article, friends have any suggestions or comments please contact me to improve oh, your support is my biggest motivation!! This article is published by OpenWrite, a platform for operating tools such as mass blog posts