High concurrent programming in real-world java Chapter 2

 1. Basic state of threads 
 2. Basic operations of threads 
 3. volatile and java Memory Model 
 4. Thread Group 
 5. Daemon 
 6. Thread priority 
 7. Thread Safety and Synchronization 
 8. Hidden Errors 

1. Basic state of threads

  1. Thread life cycle

2. Basic operations of threads

1. New threads

    Thread tl=new Thread(){
        @override
        public void run(){
            System.out.println("Hel1o,I am t1");
        };
        t1.start();
    t1.start();

2. Termination of threads

Thread.stop()    //Terminate all thread activities immediately

stop() method terminates the thread directly when it terminates, and releases the lock held by the thread immediately, which may cause data inconsistency. It is strongly recommended not to use it!!

    //Approaches to Stop Threads Correctly
    public static class ChangeObjectThread extends Thread {
        volatile boolean stopme = false;     //Tag bit, record whether to stop threads
        
        public void stopMe(){
            stopme = true;
        }
        @Override
        public void run() {
            while (true) {
                if (stopme){                //Stop threads where appropriate to avoid data inconsistencies
                    System.out.println("exit by stop me");
                    break;
                }
                synchronized (u) {
                    int v = (int) (System.currentTimeMillis() / 1000);
                    u.setId(v);
                    //Oh, do sth. else
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    u.setName(String.valueOf(v));
                }
                Thread.yield();
            }
        }
    }

3. Thread interruption

public void Thread.interrupt()        //Interrupt threads, send notifications only, set tag bits, and wait for the appropriate time to interrupt threads
public boolean Thread.isInterrupted()    //Determine whether it is interrupted or not, and determine the marker bit
public static boolean Thread.interrupted()//Determine whether an interrupt has occurred and clear the current interrupt status
Thread tl=new Thread(){
    @Override
    public void run(){
        while(true){
            if(Thread.currentThread().isInterrupted()){    //Interrupt handling methods need to be set up, otherwise interrupts cannot be responded to.
                System.out.println("Interruted!");
                break;
            )
            Thread.yield();
}
public class InterruputSleepThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(){
            @Override
            public void run(){
                while(true){
                    if(Thread.currentThread().isInterrupted()){
                        System.out.println("Interruted!");
                        break;
                    }
                    try {
                        Thread.sleep(2000);            //Throwing an exception due to interruption clears the interrupt flag
                    } catch (InterruptedException e) {
                        System.out.println("Interruted When Sleep");    //After sleep is interrupted, reset tag bits continue to run to ensure data consistency and integrity
                        //Setting interrupt status
                        Thread.currentThread().interrupt();
                    }
                    Thread.yield();
                }
            }
        };
        t1.start();
        Thread.sleep(2000);
        t1.interrupt();
    }
}

4. Wait and notify

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

The object.wait() and object.notify() methods must be included in the synchronized keyword because the monitor object is to be retrieved.

public class SimpleWN {
    final static Object object = new Object();
    public static class T1 extends Thread{
        public void run()
        {
            synchronized (object) {
                System.out.println(System.currentTimeMillis()+":T1 start! ");
                try {
                    System.out.println(System.currentTimeMillis()+":T1 wait for object ");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(System.currentTimeMillis()+":T1 end!");
            }
        }
    }
    public static class T2 extends Thread{
        public void run()
        {
            synchronized (object) {
                System.out.println(System.currentTimeMillis()+":T2 start! notify one thread");
                object.notify();
                System.out.println(System.currentTimeMillis()+":T2 end!");
                try {
                    Thread.sleep(2000);        //Here sleep()2 seconds, T1 still needs to wait 2 seconds to continue execution.
                } catch (InterruptedException e) {
                }
            }
        }
    }
    public static void main(String[] args) {
        Thread t1 = new T1() ;
        Thread t2 = new T2() ;
        t1.start();
        t2.start();
        //Output:
        //1565249714094:T1 start! 
        //1565249714094:T1 wait for object 
        //1565249714094:T2 start! notify one thread
        //1565249714094:T2 end!
        //1565249716094:T1 end!
    }
} 
    The difference between wait() and sleep():
1.wait must be used within synchronization conditions, which sleep does not require.
2.wait releases lock, sleep does not release
 3.wait is the instance method in Object and sleep is the static method in Thread.
4.wait needs to call the notify method of the object to wake up. sleep knows the time is over or is interrupted by interrupt.

5. Suspend and resume

Abandoned methods, no introduction!!! There is a need to use wait and notify

6. Waiting for the thread to join and yield modestly

public final void join() throws InterruptedException    //Blocking threads until the end
public final synchronized vold join(long millis)throws InterruptedException    //Give the maximum waiting time

The mechanism of join is actually to call a thread to loop wait in a method, as follows: join() core code:

while(isAlive()){
    wait(0);
}
public static native void yield();

yield() method means that the current thread gives up cpu computing resources, but still participates in the contest for cpu resources. It is generally used to prevent low priority threads from occupying too much cpu resources.

3. volatile and java Memory Model

volatile keywords can guarantee certain atomicity, but they can not replace locks, and can not guarantee 100% thread safety.
volatile guarantees visibility and orderliness, acts as a memory fence and prohibits command replays

4. Thread Group

  Thread groups can be used when there are more threads in a system and the allocation of functions is clear.
  

public class ThreadGroupName implements Runnable {
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("PrintGroup");
        Thread t1 = new Thread(tg, new ThreadGroupName(), "T1");
        Thread t2 = new Thread(tg, new ThreadGroupName(), "T2");
        t1.start();
        t2.start();
        System.out.println(tg.activeCount());    //2
        tg.list();        //java.lang.ThreadGroup[name=PrintGroup,maxpri=10]
                          //    Thread[T1,5,PrintGroup]
                          //    Thread[T2,5,PrintGroup]
    }
    @Override
    public void run() {
        String groupAndName = Thread.currentThread().getThreadGroup().getName()
                + "-" + Thread.currentThread().getName();
        while (true) {
            System.out.println("I am " + groupAndName);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

activeCount() Gets the number of active threads in the thread group
list() prints all thread information in the thread group

5. Daemon

Daemon threads execute in the background, such as garbage collection threads, which correspond to user threads. When the object that daemon threads want to guard does not exist, daemon threads automatically exit.
When only daemon threads exist in a java application, the java virtual machine automatically exits

public class DaemonDemo {
    public static class DaemonT extends Thread{
        public void run(){
            while(true){
                System.out.println("I am alive");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t=new DaemonT();
        t.setDaemon(true);    //This method must precede the start method
        t.start();
        
        Thread.sleep(2000);
    }
}

In the above code, t is set as a daemon thread, and when the main thread exits, the daemon thread will also exit. If not set as a daemon thread, the T thread will still print after the main thread exits.

6. Thread priority

Threads can set priority. Threads with higher priority have a higher probability of getting cpu resources (but not necessarily getting cpu resources before threads with lower priority)
public class PriorityDemo {
    public static class HightPriority extends Thread{
        static int count=0;
        public void run(){
            while(true){
                synchronized(PriorityDemo.class){       //The purpose of locking this class here is to create a resource competition and make the priority difference more obvious.
                    count++;
                    if(count>10000000){
                        System.out.println("HightPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    public static class LowPriority extends Thread{
        static int count=0;
        public void run(){
            while(true){
                synchronized(PriorityDemo.class){
                    count++;
                    if(count>10000000){
                        System.out.println("LowPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    /**
     * HightPriority There are many times to finish first, but there is no guarantee.
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Thread high=new HightPriority();
        LowPriority low=new LowPriority();
        high.setPriority(Thread.MAX_PRIORITY);    //This method can set priority 0-10 digits
        low.setPriority(Thread.MIN_PRIORITY);
        low.start();
        high.start();
    }
}
HightPriority is always faster than LowPriority on multiple trials, but there is no guarantee that it will.

7. Thread Safety and Synchronization

synchronized is a heavyweight synchronization lock, which realizes the synchronization between threads. The object, method and code block locked by sychronize can only be accessed by one thread at a time, thus ensuring the safety of threads.

    Usage:
    
Specified lock object: synchronized(object) {....}
Specify instance method: public synchronized void println ()
Specify a static method: public static synchronized void println()
public class BadAccountingSync2 implements Runnable{
    static int i=0;
    public static synchronized void increase(){        //If static is not applied here, the thread is unsafe and the final i value must be less than 2000.
        i++;
    }
    @Override
    public void run() {
        for(int j=0;j<10000;j++){
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(new BadAccountingSync2());
        Thread t2=new Thread(new BadAccountingSync2());
        t1.start();t2.start();
        t1.join();t2.join();
        System.out.println(i);     //Output 20000
    }
}

8. Hidden Errors

To be continued...

Keywords: Java less

Added by iamtheironman on Thu, 08 Aug 2019 13:18:16 +0300