Detailed explanation of the use of Java multithreading

  • 2020-04-01 01:41:54
  • OfStack

1. Create threads

  There are two ways to create threads in Java: using the Thread class and using the Runnable interface. A Thread instance needs to be set up when using the Runnable interface. Therefore, whether a Thread is created through the Thread class or the Runnable interface, an instance of the Thread class or its subclasses must be created. Thread constructor:

Public Thread ();   Public Thread (Runnable target);   Public Thread (String name);   Public Thread(Runnable target, String name);   Public Thread(ThreadGroup group, Runnable target);   Public Thread(ThreadGroup group, String name);   Public Thread(ThreadGroup group, Runnable target, String name);   Public Thread(ThreadGroup group, Runnable target, String name, long stackSize);

Method 1: inherit the Thread class to override the run method


public class ThreadDemo1 {
     public static void main(String[] args){
         Demo d = new Demo();
         d.start();
         for(int i=0;i<60;i++){
             System.out.println(Thread.currentThread().getName()+i);
         }

     }
 }
 class Demo extends Thread{
     public void run(){
         for(int i=0;i<60;i++){
             System.out.println(Thread.currentThread().getName()+i);
         }
     }
 }

Method 2:

public class ThreadDemo2 {
    public static void main(String[] args){
        Demo2 d =new Demo2();
        Thread t = new Thread(d);
        t.start();
        for(int x=0;x<60;x++){
            System.out.println(Thread.currentThread().getName()+x);
        }
    }
}
class Demo2 implements Runnable{
    public void run(){
        for(int x=0;x<60;x++){
            System.out.println(Thread.currentThread().getName()+x);
        }
    }
}

2. Thread life cycle

  Just as a human being dies, a thread goes through four different states: start (wait), run, suspend, and stop. All four states can be controlled through methods in the Thread class. The methods for the Thread class to correlate these four states are shown below.

// start thread Publicvoid start ();   Publicvoid run ();   // suspend and wake up threads Publicvoid resume ();         // not recommended Publicvoid suspend ();       // not recommended Publicstaticvoid sleep (long millis);   Publicstaticvoid sleep(long millis, int nanos);   // thread termination Publicvoid stop ();             // not recommended Publicvoid interrupt ();   // gets the thread state Publicboolean isAlive ();   Publicboolean isInterrupted ();   Publicstaticboolean interrupted ();   / / join method Publicvoid join() throws InterruptedException;  

 

      The thread does not execute the code in the run method immediately after it is created, but is in a wait state. When a Thread is in a waiting state, the methods of the Thread class can be used to set various properties of the Thread, such as the priority of the Thread, the name of the Thread, and the type of the Thread (setDaemon).

    When the start method is called, the thread starts executing the code in the run method. The thread enters a running state. The isAlive method of the Thread class can be used to determine whether a Thread is running. When the thread is running, isAlive returns true, and when isAlive returns false, the thread may be in a wait state or a stop state. The following code illustrates the switch between creating, running, and stopping the thread, and outputs the corresponding isAlive return value.

    Once a thread starts executing the run method, it does not exit until the run method completes. But during a thread's execution, there are two ways to temporarily stop the thread from executing. The two methods are suspend and sleep. After suspending a thread with suspend, you can wake it up with the resume method. When sleep is used to make a thread sleep, the thread can only be in the ready state after a set time (after the thread sleep ends, the thread does not necessarily execute immediately, it just enters the ready state and waits for the system to schedule).

There are two things to note when using the sleep method:

1. The sleep method has two overloads, one of which can set not only milliseconds but also nanoseconds (1,000,000 nanoseconds = 1 millisecond). However, the Java virtual machine on most operating system platforms is not accurate to nanoseconds, so if you set the nanosecond for sleep, the Java virtual machine will take the nearest millisecond to that value.

2. You must use throws or try{... } catch {... }. Since the run method cannot use throws, only try{... } catch {... }. When you interrupt a thread while it is asleep, sleep throws an InterruptedException when the thread is interrupted. The definition of the sleep method is as follows:

public The static void Sleep ( long Millis) throws InterruptedException public The static void Sleep ( long Millis, int Nanos) throws InterruptedException

There are three ways to terminate a thread.

1.   The exit flag is used to make the thread exit normally, that is, the thread terminates when the run method completes.

2.   Forcibly terminate a thread using the stop method (which is not recommended because stop, like suspend and resume, can have unpredictable results).

3.   Interrupt a thread with an interrupt method.

Use the exit flag to terminate the thread

  When the run method is finished, the thread exits. But sometimes the run method never ends. Such as using threads to listen to client requests in a server-side program, or other tasks that require looping. In this case, it is common to put these tasks in a loop, such as a while loop. If you want the loop to run forever, you can use the while(true){... } to handle. But the most straightforward way to make the while loop exit under a particular condition is to set a Boolean flag and control whether or not the while loop exits by setting the flag to true or false. An example of thread termination using the exit flag is given below.

    What the join method does is make asynchronous threads execute synchronously. That is, when the start method of the thread instance is called, the method returns immediately, and if a value calculated by the thread is needed after the start method is called, the join method must be used. If you do not use the join method, there is no guarantee that the thread will finish executing when a statement following the start method is executed. With the join method, the program does not execute until the thread exits. The following code demonstrates the use of join.

  3. Multithreading security problem

  Reason for the problem: when multiple statements are operating on the same thread to share data, one thread only executes part of the multiple statements, and the other thread participates in the execution, resulting in the error of sharing data.

  Solution: for statements that share data for multiple operations, only one thread can execute. During execution, other threads do not execute.

Synchronized code block:


public class ThreadDemo3 {
    public static void main(String[] args){
        Ticket t =new Ticket();
        Thread t1 = new Thread(t," A window ");
        Thread t2 = new Thread(t," Window 2 ");
        Thread t3 = new Thread(t," Window 3 ");
        Thread t4 = new Thread(t," Window four ");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
class Ticket implements Runnable{
    private int ticket =400;
    public void run(){
        while(true){
            synchronized (new Object()) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if(ticket<=0)
                    break;
                System.out.println(Thread.currentThread().getName()+"--- sell "+ticket--);
            }
        }
    }
}

Synchronization function

public class ThreadDemo3 {
    public static void main(String[] args){
        Ticket t =new Ticket();
        Thread t1 = new Thread(t," A window ");
        Thread t2 = new Thread(t," Window 2 ");
        Thread t3 = new Thread(t," Window 3 ");
        Thread t4 = new Thread(t," Window four ");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
class Ticket implements Runnable{
    private int ticket = 4000;
    public synchronized void  saleTicket(){
        if(ticket>0)
            System.out.println(Thread.currentThread().getName()+" sold "+ticket--);

    }
    public void run(){
        while(true){
            saleTicket();
        }
    }
}

The sync function lock is this static sync function lock is class

Communication between threads


public class ThreadDemo3 {
    public static void main(String[] args){
        class Person{
            public String name;
            private String gender;
            public void set(String name,String gender){
                this.name =name;
                this.gender =gender;
            }
            public void get(){
                System.out.println(this.name+"...."+this.gender);
            }
        }
        final Person p =new Person();
        new Thread(new Runnable(){
            public void run(){
                int x=0;
                while(true){
                    if(x==0){
                        p.set(" Zhang SAN ", " male ");
                    }else{
                        p.set("lili", "nv");
                    }
                    x=(x+1)%2;
                }
            }
        }).start();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    p.get();
                }
            }
        }).start();
    }
}


Modify the above code

public class ThreadDemo3 {
     public static void main(String[] args){
         class Person{
             public String name;
             private String gender;
             public void set(String name,String gender){
                 this.name =name;
                 this.gender =gender;
             }
             public void get(){
                 System.out.println(this.name+"...."+this.gender);
             }
         }
         final Person p =new Person();
         new Thread(new Runnable(){
             public void run(){
                 int x=0;
                 while(true){
                     synchronized (p) {
                         if(x==0){
                             p.set(" Zhang SAN ", " male ");
                         }else{
                             p.set("lili", "nv");
                         }
                         x=(x+1)%2;    
                     }

                 }
             }
         }).start();
         new Thread(new Runnable(){
             public void run(){
                 while(true){
                     synchronized (p) {
                         p.get();
                     }
                 }
             }
         }).start();
     }

 }
 

Wait wake mechanism


public class ThreadDemo3 {
    private static boolean flags =false;
    public static void main(String[] args){
        class Person{
            public String name;
            private String gender;
            public void set(String name,String gender){
                this.name =name;
                this.gender =gender;
            }
            public void get(){
                System.out.println(this.name+"...."+this.gender);
            }
        }
        final Person p =new Person();
        new Thread(new Runnable(){
            public void run(){
                int x=0;
                while(true){
                    synchronized (p) {
                        if(flags)
                            try {
                                p.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            };
                        if(x==0){
                            p.set(" Zhang SAN ", " male ");
                        }else{
                            p.set("lili", "nv");
                        }
                        x=(x+1)%2;
                        flags =true;
                        p.notifyAll();
                    }
                }
            }
        }).start();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    synchronized (p) {
                        if(!flags)
                            try {
                                p.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            };
                        p.get();
                        flags =false;
                        p.notifyAll();
                        }
                }
            }
        }).start();
    }
}

Production and consumption mechanism one

public class ThreadDemo4 {
    private static boolean flags =false;
    public static void main(String[] args){
        class Goods{
            private String name;
            private int num;
            public synchronized void produce(String name){
                if(flags)
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                this.name =name+" No. : "+num++;
                System.out.println(" Production of the ...."+this.name);
                flags =true;
                notifyAll();
            }
            public synchronized void consume(){
                if(!flags)
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                System.out.println(" The consumption ******"+name);
                flags =false;
                notifyAll();
            }

        }
        final Goods g =new Goods();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    g.produce(" goods ");
                }
            }
        }).start();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    g.consume();
                }
            }
        }).start();
    }
}

Production and consumption mechanism 2

public class ThreadDemo4 {
    private static boolean flags =false;
    public static void main(String[] args){
        class Goods{
            private String name;
            private int num;
            public synchronized void produce(String name){
                while(flags)
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                this.name =name+" No. : "+num++;
                System.out.println(Thread.currentThread().getName()+" Production of the ...."+this.name);
                flags =true;
                notifyAll();
            }
            public synchronized void consume(){
                while(!flags)
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                System.out.println(Thread.currentThread().getName()+" The consumption ******"+name);
                flags =false;
                notifyAll();
            }

        }
        final Goods g =new Goods();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    g.produce(" goods ");
                }
            }
        }," Producer one ").start();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    g.produce(" goods ");
                }
            }
        }," Producer two ").start();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    g.consume();
                }
            }
        }," Consumer one ").start();
        new Thread(new Runnable(){
            public void run(){
                while(true){
                    g.consume();
                }
            }
        }," Consumer 2 ").start();
    }
}



Related articles: