Multithreading in Java concurrent programming

Operating system adjusted the minimum degree of single element is a wire drive

Multiple threads can be created in a process. These threads have their own counters, stacks, and local variables, and can access shared memory variables. The processor switches on these threads at high speed, making it feel that these threads are executing at the same time.

Thread priority

The operating system basically schedules running threads in the form of time division. The operating system will allocate time slices one by one, and threads will be allocated several time slices. When the thread time slices are used up, thread scheduling will occur and wait for the next allocation. The time slice allocated to the thread determines how much processor resources the thread uses, and the thread priority is the thread attribute that determines how much or less the thread needs to allocate some processor resources.

In Java threads, the priority ranges from 1 to 10, and the default priority is 5. The threads with higher priority are allocated more time slices than threads with lower priority.

Thread status

public class ThreadState {


    private static Lock lock = new ReentrantLock();


public static void main(String[] args) {

//线程被构建,处于NEW状态

Thread thread=new Thread(new TimeWaiting(), "TimeWaitingThread");

//线程开始,即将进入RUNNABLE状态

        thread.start();

        new Thread(new Waiting(), "WaitingThread").start();

        // 使用两个Blocked线程,一个获取锁成功,另一个被阻塞

        new Thread(new Blocked(), "BlockedThread-1").start();

        new Thread(new Blocked(), "BlockedThread-2").start();

        new Thread(new Sync(), "SyncThread-1").start();

        new Thread(new Sync(), "SyncThread-2").start();

    }


    /**

     * 该线程不断的进行睡眠

     */

    static class TimeWaiting implements Runnable {

        @Override

        public void run() {

            while (true) {

                SleepUtils.second(100);

            }

        }

    }


    /**

     * 该线程在Waiting.class实例上等待

     */

    static class Waiting implements Runnable {

        @Override

        public void run() {

            while (true) {

                synchronized (Waiting.class) {

                    try {

                        Waiting.class.wait();

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                }

            }

        }

    }


    /**

     * 该线程在Blocked.class实例上加锁后,不会释放该锁

     */

    static class Blocked implements Runnable {

        public void run() {

            synchronized (Blocked.class) {

                while (true) {

                    SleepUtils.second(100);

                }

            }

        }

    }


    static class Sync implements Runnable {


        @Override

        public void run() {

            lock.lock();

            try {

                SleepUtils.second(100);

            } finally {

                lock.unlock();

            }


        }


    }

}

Analyze thread running status through jstack pid:

 

Java thread state transition

Note: Java combines the running and ready states in the operating system as the running state. The blocking state is the state when the thread is blocked when entering the method or code block modified by the synchronized keyword (acquiring the lock), but the thread state blocked in the Lock interface in the java.concurrent package is a waiting state, because the Lock interface in the java.concurrent package For the implementation of blocking, the relevant methods in the LockSupport class are used.

 

Daemon thread is a kind of support thread, because it is mainly used for background scheduling and supporting work in the program. When there are no non-Daemon threads in a Java virtual machine, the Java virtual machine will exit.

 

Note: The Daemon attribute needs to be set before starting the thread, and cannot be set after starting the thread.

The Daemon thread is used to complete supporting work, but the finally block in the Daemon thread is not necessarily executed when the Java virtual machine exits

Thread interruption

Interruption can be understood as a flag attribute of a thread, which indicates whether a running thread has been interrupted by other threads. Interruption is like another thread greets the thread, and other threads interrupt the thread by calling the interrupt() method of the thread.

The thread responds by checking whether it is interrupted. The thread uses the method isInterrupted() to determine whether it is interrupted. You can also call the static method Thread.interrupted() to reset the interrupt flag of the current thread. If the thread is already in the terminal state, even if the thread has been interrupted, it will still return false when calling the isInterrupted() of the thread object.

 

Note: The suspend(), resume() and stop() methods complete the suspension, resumption and termination of threads, and they are very "humane". But these APIs are out of date, which is not recommended.

 

The keyword volatile can be used to modify the field (member variable), that is, to inform the program that any access to the variable needs to be obtained from the shared memory, and changes to it must be flushed back to the shared memory synchronously. It can ensure that all threads access the variable Visibility.

The keyword synchronized can be used to modify the method or in the form of a synchronized block. It mainly ensures that multiple threads can only be in the method or synchronized block at the same time. It ensures the visibility and visibility of the thread's access to variables. Exclusivity.

public class Synchronized {

    public static void main(String[] args) {

        // 对Synchronized Class对象进行加锁

        synchronized (Synchronized.class) {


        }

        // 静态同步方法,对Synchronized Class对象进行加锁

        m();

    }


    public static synchronized void m() {

    }

}

通过javap -v Synchronized.class

 The Java class file decomposer can decompile (that is, decompile the files compiled by javac), and you can also view the bytecode generated by the java compiler. Used to decompose class files.

For the realization of the synchronization block, the monitorenter and monitorexit instructions are used, and the synchronization method is completed by the ACC_SYNCHRONIZED on the method modifier.

Waiting/notification mechanism

1) When using wait(), notify() and notifyAll(), you need to lock the calling object first.

2) After calling the wait() method, the thread state changes from RUNNING to WAITING, and the current thread is placed in the waiting queue of the object.

3) After the notify() or notifyAll() method is called, the waiting thread will still not return from wait(). After the thread that calls notify() or notifAll() releases the lock, the waiting thread has the opportunity to return from wait().

4) The notify() method moves a waiting thread in the waiting queue from the waiting queue to the synchronization queue, while the notifyAll() method moves all the threads in the waiting queue to the synchronization queue. The state of the moved thread is determined by WAITING becomes BLOCKED.

5) The premise of returning from the wait() method is to obtain the lock of the calling object.

public class WaitNotify {

    static boolean flag = true;

    static Object  lock = new Object();


    public static void main(String[] args) throws Exception {

        Thread waitThread = new Thread(new Wait(), "WaitThread");

        waitThread.start();

        TimeUnit.SECONDS.sleep(1);


        Thread notifyThread = new Thread(new Notify(), "NotifyThread");

        notifyThread.start();

    }


    static class Wait implements Runnable {

        public void run() {

            // 加锁,拥有lock的Monitor

            synchronized (lock) {

                // 当条件不满足时,继续wait,同时释放了lock的锁

                while (flag) {

                    try {

                        System.out.println(Thread.currentThread() + " flag is true. wait @ "

                                           + new SimpleDateFormat("HH:mm:ss").format(new Date()));

                        lock.wait();

                    } catch (InterruptedException e) {

                    }

                }

                // 条件满足时,完成工作

                System.out.println(Thread.currentThread() + " flag is false. running @ "

                                   + new SimpleDateFormat("HH:mm:ss").format(new Date()));

            }

        }

    }


    static class Notify implements Runnable {

        public void run() {

            // 加锁,拥有lock的Monitor

            synchronized (lock) {

                // 获取lock的锁,然后进行通知,通知时不会释放lock的锁,

                // 直到当前线程释放了lock后,WaitThread才能从wait方法中返回

                System.out.println(Thread.currentThread() + " hold lock. notify @ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));

                lock.notifyAll();

                flag = false;

                SleepUtils.second(5);

            }

            // 再次加锁

            synchronized (lock) {

                System.out.println(Thread.currentThread() + " hold lock again. sleep @ "

                                   + new SimpleDateFormat("HH:mm:ss").format(new Date()));

                SleepUtils.second(5);

            }

        }

}

WaitThread first acquires the lock of the object, and then calls the wait() method of the object, thereby giving up the lock and entering the WaitQueue of the object, entering the waiting state. Because WaitThread released the lock of the object, NotifyThread subsequently acquired the lock of the object and called the notify() method of the object to move the WaitThread from WaitQueue to

In SynchronizedQueue, the status of WaitThread becomes blocked at this time. After NotifyThread releases the lock, WaitThread acquires the lock again and returns from the wait() method to continue execution.

Thread.join()

The current thread A waits for the thread thread to terminate before returning from thread.join()

ThreadLocal

It is a storage structure with ThreadLocal objects as keys and arbitrary objects as values. This structure is attached to the thread, which means that a thread can query a value bound to this thread based on a ThreadLocal object.

Guess you like

Origin blog.csdn.net/weixin_44416039/article/details/86160970