Java multithreading 1: the use of threads

Overview

A process is a container of threads. Threads share the memory space of a process, so it is relatively easy for threads to communicate with each other, and threads have their own private memory addresses, which cannot be accessed by other threads. Understand the relationship between processes and threads, you can see my other blog "process and thread"

Two ways to create threads in Java

Inherit Thread class

public class ThreadDemo1 extends Thread {

    @Override
    public void run(){
        for (int i = 0; i < 10; i++) {
            System.out.println ( "The currently executing thread is" + Thread.currentThread (). GetName ());
        }
    }

    public static void main(String[] args) {
        ThreadDemo1 threadDemo1 = new ThreadDemo1();
        ThreadDemo1 threadDemo2 = new ThreadDemo1();
        threadDemo1.start();
        threadDemo2.start();
    }
}

The execution result is uncertain

Implement Runnable

public class ThreadDemo2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            for (int j = 0;j < 1000; ++j){
                System.out.println (i + "The currently executing thread is" + Thread.currentThread (). GetName ());
            }
        }
    }

    public static void main(String[] args) {
        ThreadDemo2 threadDemo1 = new ThreadDemo2();
        ThreadDemo2 threadDemo2 = new ThreadDemo2();
        Thread thread1 = new Thread(threadDemo1);
        Thread thread2 = new Thread(threadDemo2);
        thread1.start();
        thread2.start();
        System.out.println ( "The current thread is ===>" + Thread.currentThread (). GetName ());
    }
}

The name of the main thread is main, and the name of the non-main thread is specified by the virtual machine. At the same time, we can also specify a specific name for the thread.

 We guarantee that each thread can start normally, it does not mean that it will be executed in order, because the scheduler cannot guarantee its execution order, and at the same time, when the run () function ends, it means that the task of the thread is completed. .

Note: The calling thread must call start. If run is called, it is just a simple object call.

Thread life cycle

    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

 

New status

After the thread object is created, it enters the new state Thread thread = new Thread

Ready state

Calling the start () method, the thread enters the ready state, but it does not mean that the thread is executed immediately, it just means that the thread is ready to wait for the CPU to schedule execution at any time.

Blocked state

Multiple threads compete for an exclusive lock at the same time, and other threads that do not grab the lock will enter the blocking state and be placed in the lock pool until the lock is acquired and enter the ready state.

Wait state

The thread needs to wait for other threads to make some specific actions, notify or interrupt, wait for it to be awakened by other threads, like CountDownLatch can wait for one or several threads to end.

Timeout wait state

Different from the waiting state, it can return on its own at a specified time. The sheep (long) function will make the thread enter the timeout waiting state, and then it will be in the ready state when the time is up.

Running status (Running)

When the CPU schedules a thread in a ready state, this thread is actually executed and enters the running state.

Termination state

After the normal execution of the thread is completed or it is forced to terminate early or an exception occurs, the thread will be destroyed to release resources.

Thread method invocation

Get basic thread information

public class ThreadDemo6 {
    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public  void run () {
                 / * Get the unique ID of the thread * / 
                long id = this .getId ();
                System.out.println("thread的ID==>" + id);

                / * Get thread name * / 
                String name = this .getName ();
                System.out.println("thread的名字==>" + name);

                / * Get the priority of the thread by default 5 1-10 * / 
                int priority = this .getPriority ();
                System.out.println ( "Thread priority ==>" + priority);

                / * Check if the current thread is a daemon thread * / 
                boolean isDaemon = this .isDaemon ();
                System.out.println ( "Whether thread is a daemon thread ==>" + isDaemon);

                / * Check if the thread is interrupted * / 
                boolean isInterrupted = this .isInterrupted ();
                System.out.println ( "Whether the thread is interrupted ==>" + isInterrupted);
            }
        };
        thread.start();
    }
}

Results of the

thread ID ==> 11 
thread name ==> Thread-0 
thread priority ==> 5 
thread is a daemon thread ==> false 
thread is interrupted ==> false

Thread.yield()

public class ThreadDemo1 implements Runnable {
    protected int countDown = 10;
    private static int taskCount = 0;
    private final int id = taskCount++;
    public ThreadDemo1(){}
    public ThreadDemo1(int countDown){
        this.countDown = countDown;
    }
    public String status(){
        return "#" + id + "(" + (countDown > 0 ? countDown : "stop!") + ")";
    }


    @Override
    public void run() {
        while (countDown-- > 0){
            System.out.println(status() + "  ");
            Thread.yield();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++){
            new Thread(new ThreadDemo1()).start();
        }
    }
}
#0(9)#0(8)#0(7)#0(6)#0(5)#0(4)#0(3)#0(2)#0(1)#0(stop!)
#1(9)#1(8)#1(7)#1(6)#1(5)#1(4)#1(3)#1(2)#1(1)#1(stop!)
#2(9)#2(8)#2(7)#2(6)#2(5)#2(4)#2(3)#2(2)#2(1)#2(stop!)

This is a countdown task, and the call to Thread.yield () is a suggestion to the thread scheduler. It states that "I have performed the most important part of the life cycle. At this moment, it is switching to other tasks to perform "It's a good time". To put it bluntly is to press the pause button to give up your CPU usage rights and turn it into a ready state. It is not necessarily when you can get CPU scheduling next time. Sometimes it is fast, sometimes you have to wait for a while .

Thread.sleep

public class ThreadDemo1 implements Runnable {
    protected int countDown = 10;
    private static int taskCount = 0;
    private final int id = taskCount++;
    public ThreadDemo1(){}
    public ThreadDemo1(int countDown){
        this.countDown = countDown;
    }
    public String status(){
        return "#" + id + "(" + (countDown > 0 ? countDown : "stop!") + ")";
    }


    @Override
    public void run() {
        try {
            while (countDown-- > 0){
                System.out.println(status());
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace ();
        }

    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++){
            new Thread(new ThreadDemo1()).start();
        }
    }
}

 

Thread.sleep (long) will cause the "executing task" to suspend execution for a given time (suspend execution) and give up CPU usage rights. This statement is equivalent to saying that within the next 1 second, you do n’t call me, I want to sleep for a while. After 1 second of sleep time, it will automatically change to the ready state, but the CPU may not immediately execute this wake-up thread, depending on whether the CPU time segment is grabbed. It is worth noting that if the sleep and yield contexts are locked, they still use the lock and will not release it. The biggest difference between sleep and yield is that yield does not let the thread enter the waiting state, but only turns the thread into the ready state, and gives up the CPU execution opportunity to the thread with the same priority or higher, and sleep can control the specific handover of the CPU Time of use.

Thread.currentThread()

 

public class ThreadDemo2 extends Thread {
    static {
        System.out.println ( "Thread executed by static block ===>" + Thread.currentThread (). GetName ());
    }
    {
        System.out.println ( "The thread of non-static block execution is ====>" + Thread.currentThread (). GetName ());
        System.out.println("this.getName()1=====>" + this.getName());
    }

    public ThreadDemo2(){
        System.out.println ( "Thread executed in the constructor ====>" + Thread.currentThread (). GetName ());
        System.out.println("this.getName()2=====>" + this.getName());
    }

    @Override
    public void run() {
        System.out.println ( "The currently executing thread is ====>" + Thread.currentThread (). GetName ());
        System.out.println("this.getName()3=====>" + this.getName());
    }

    public static void main(String[] args) {
        ThreadDemo2 threadDemo2 = new ThreadDemo2();
        threadDemo2.start();
    }
}

Results of the

Thread executed by static block ===> main
The thread executed by the non-static block is ====> main
 this .getName () 1 =====> 
the thread executed in the Thread-0 constructor ====> main
 this .getName () 2 ==== => Thread-0 
currently executing thread is ====> Thread-0
 this .getName () 3 =====> Thread-0

The currentThread returns a reference to the currently executing thread object. It is obviously different from this.getName (). The static block and non-static block are executed. The thread of the constructor is main, not ThreadDemo2, and the run () method is executed. It is the threadDemo2 that is instantiated. Therefore, the Thread currently being executed is not necessarily the Thread itself.

isAlive()

public class ThreadDemo3 extends Thread {
    @Override
    public void run(){
        System.out.println ( "Execution execution ====" + this .isAlive ());
    }

    public static void main(String[] args) {
        ThreadDemo3 threadDemo3 = new ThreadDemo3();
        System.out.println("begin===>" + threadDemo3.isAlive());
        threadDemo3.start();
        System.out.println("end==>" + threadDemo3.isAlive());
    }
}
begin ===> false 
end ==> true 
execute execution ==== true

isAlive () detects whether the thread is active, the active status returns true

setPriority ()

Priority setting, the easier the thread with the higher priority gets the CPU usage right,

public class ThreadDemo4 {
    public static void main(String[] args) {
        for (int i = 0; i < 5; ++i){
            Thread1 thread1 = new Thread1();
            thread1.setPriority(6);
            Thread2 thread2 = new Thread2();
            thread2.setPriority(4);
            thread2.start();
            thread1.start();
        }
    }
}
class Thread1 extends  Thread{
    @Override
    public void run(){
        for (int i = 0; i < 100000; ++i){
            System.out.println("+++++++++++++");
        }
    }
}
class Thread2 extends Thread{

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

Results of the

+++++++++++++
+++++++++++++
+++++++++++++
+++++++++++++
+++++++++++++
+++++++++++++
+++++++++++++
+++++++++++++
...

CPU will try to give resources to threads with high priority

setDaemon()

The daemon thread is also called the acquired thread. The threads we create are all foreground threads by default. In terms of use, there is no difference between the daemon thread and the foreground thread. The difference is that the process ends, when all foreground threads in a process end At this time, regardless of whether the daemon threads in this process are still running, they must be forced to end. In other words, the foreground thread is over, and the daemon thread will be automatically destroyed. It exists for the convenience of other threads.

/*rose与jack*/
public class ThreadDemo5 {
    public static void main(String[] args) {
        Rose rose = new Rose();
        Jack jack = new Jack ();
         / * Set to daemon thread must be before the thread is not started * / 
        jack.setDaemon ( true );
        rose.start();
        jack.start();
    }
}
class Rose extends Thread{
    @Override
    public void run(){
        for (int i = 0; i < 5; ++i){
            System.out.println("rose: let me go!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }
        }
        System.out.println ( "Successful diving" );
    }
}
class Jack extends Thread{
    @Override
    public void run(){
        while (true){
            System.out.println("jack:you jump! i jump!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }
        }
    }
}

Results of the

rose: let me go!
jack:you jump! i jump!
rose: let me go!
jack:you jump! i jump!
rose: let me go!
jack:you jump! i jump!
rose: let me go!
jack:you jump! i jump!
rose: let me go!
jack:you jump! i jump!
成功跳水

Jack guards rose, jack is the guardian thread. When rose dives, jack thinks he is not necessary to be alive anymore, and he destroys it himself, but note that there is a third party main among them, which requires that main also run jack The thread will be destroyed.

join()

This method can coordinate multiple threads to run synchronously. The multi-threaded operation itself is designed to run asynchronously, but in the program running business, it is possible that the calculation of thread A requires the return result of thread B, which requires them to perform their respective tasks. Successively, join needs to coordinate these threads to run synchronously.

public class ThreadDemo6 {
    private static boolean isFinish = false;

    public static void main(String[] args) {
        Thread download = new Thread(){
            @Override
            public void run(){
                System.out.println ( "Downloading pictures ..." );
                 for ( int i = 1; i <= 100; ++ i) {
                    System.out.println ( "Download progress" + i + "%" );
                     try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace ();
                    }
                }
                System.out.println ( "Image download finished" );
                isFinish = true;
            }
        };
        Thread show = new Thread(){
            @Override
            public void run(){
                System.out.println ( "Start displaying pictures ..." );
                 try {
                    download.join();
                } catch (InterruptedException e) {
                    e.printStackTrace ();
                }
                if (! isFinish) {
                     throw  new RuntimeException ("Image download error" );
                }
                System.out.println ( "The picture is displayed normally ..." );
            }
        };
        download.start();
        show.start();
    }
}

Results of the

Downloading pictures ...
Start showing pictures ...
Download progress 1 % 
Download progress 2 %
...
Download progress 100 %
Picture downloaded
The picture is displayed normally. . .

Show calling join will cause show to block indefinitely until the down thread is destroyed. The biggest difference between it and sleep is that join will release the lock, while sleep will not.

Involving the jmm memory model, thread safety, etc., introduced later

Guess you like

Origin www.cnblogs.com/dslx/p/12664004.html