Multi-threaded Common Base

Posted by teo99 on Mon, 17 Jun 2019 18:05:53 +0200

1: Description of processes and threads:

Processes: Each process has its own code and data space (process context), and switching between processes can be costly, with 1 to n threads per process.(Process is the smallest unit of resource allocation)

Threads: The same type of thread shares code and data space, each thread has its own run stack and program counter (PC), and thread switching costs are low.(Threads are the smallest unit of cpu scheduling)

Two: Common ways to achieve multithreading:

1. Inherit the Thread class
2. Implement Runnable Interface

Three: For direct inheritance Thread

See examples:

 

public class Zy  extends Thread{

    private  String name;
    public Zy(){}

    public  Zy(String name){
        this.name = name;
    }
    public  void run(){

        for (int i=0;i<5;i++){
            System.out.println(name+"implement     "+i+"second");
        }
    }

 

 

 

public class Test {

    public static void main(String[] args) {

             Zy z1 = new Zy("z1");
             Zy z2 = new Zy("z2");
             z1.run();    //You cannot call it directly here test()Method
             z2.run();    //Here the run method hand is to override the run method of Thread before calling it to start ()
    }

}

 

 

Implement effect:

z1 executed 0 times
 z1 executed once
 z1 executed twice
 z1 executed three times
 z1 executed four times
 z2 executed 0 times
 z2 executes once
 z2 executed twice
 z2 executed three times
 z2 executed four times

 

This method is executed in the wrong order and the start() method should be called

 public static void main(String[] args) {

             Zy z1 = new Zy("z1");
             Zy z2 = new Zy("z2");
             z1.start();
             z2.start();

    }

 

Note: The effect can only be achieved if the run() method start() method in Thread is overridden.

Achieving results

z2 executed 0 times
 z1 executed 0 times
 z2 executes once
 z1 executed once
 z2 executed twice
 z1 executed twice
 z2 executed three times
 z1 executed three times
 z2 executed four times
 z1 executed four times

Since CPU resources are required, the results are basically different for each run.

As to why the run() method cannot be called directly, it should be that the running of threads requires support from the local operating system.

start0 () is called here.And this method uses the native keyword, which means a function that calls the local operating system.This is because multithreaded implementations require support from the local operating system.

 

By implementing the Runnable interface

public class Zy implements Runnable{

    private  String name;
    public Zy(){}

    public  Zy(String name){
        this.name = name;
    }
    public  void run(){

        for (int i=0;i<5;i++){
            System.out.println(name+"implement     "+i+"second");
        }
    }


}

  

  public static void main(String[] args) {

             Zy z1 = new Zy("z1");
             Thread t1 = new Thread(z1);
             Zy z2 = new Zy("z2");
             Thread t2 = new Thread(z2);
             t1.start();
             t2.start();

    }

//Execution results

For the first time:
z1 executed 0 times z1 executed once z2 executed 0 times z2 executes once z2 executed twice z2 executed three times z2 executed four times z1 executed twice z1 executed three times z1 executed four times
The second time:

z1 executed 0 times
z1 executed once
z1 executed twice
z1 executed three times
z1 executed four times
z2 executed 0 times
z2 executes once
z2 executed twice
z2 executed three times
z2 executed four times

//Each execution results are roughly different, if roughly the same, your operating system may be more stable, Huh-huh

 

About inheriting Thread or implementing the Runnable interface?

View Source Discovery

    

public
class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

Thread also implements the Runnable interface, and both Thread and Runnable implement the run method, which is actually the proxy mode.I am not sure about the proxy mode, but here: http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html

The difference between Thread and Runnable:

 

1. If a class inherits Thread, it is not suitable for resource sharing.But if you implement the Runable interface, resource sharing is easy.

This implementation inherits Thread

public class Zy extends Thread{
private  int count=5;
public void run(){

for (int i = 0; i < 6; i++) {
if (count > 0) {
System.out.println("Number= " + count--);
}
}

}
public static void main(String[] args) {

Zy z1 = new Zy();
Thread t1 = new Thread(z1);
Zy z2 = new Zy();
Thread t2 = new Thread(z2);
t1.start();
t2.start();

}
 }

 

Execution effect

Quantity = 5
 Quantity = 4
 Quantity = 3
 Quantity = 2
 Quantity = 1
 Quantity = 5
 Quantity = 4
 Quantity = 3
 Quantity = 2
 Quantity = 1

This description resource is not shared, change to runnable interface

 

public class Zy implements Runnable{

    private  int count=5;
    public  void run(){

        for (int i = 0; i < 6; i++) {
            if (count > 0) {
                System.out.println("Number= " + count--);
            }
        }

    }
    public static void main(String[] args) {

         Zy zy = new Zy();
         new Thread(zy,"1 Number window").start();
         new Thread(zy, "2 Number window").start();
         new Thread(zy, "3 Number window").start();

    }


}

(possible) effect

Quantity = 5
 Quantity = 2
 Quantity = 1
 Quantity = 3
 Quantity = 4

  

To summarize:

Implementing the Runnable interface has advantages over inheriting the Thread class:

1: For multiple threads of the same program code to process the same resource

2): can avoid single inheritance restrictions in java

3): Increase the robustness of the program, code can be shared by multiple threads, code and data independent.

 

Also, the main method is actually a thread.All threads in java start at the same time, and when and which executes first depends entirely on who gets the CPU's resources first.

In java, at least two threads are started per program run.One is the main thread and the other is the garbage collection thread.Because whenever a class is executed using a Java command, a JVM is actually started, and each jVM is actually a process started in the operating system.

 

Four: Determine if a thread is started

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

    public static void main(String[] args) {
        Zy zy = new Zy();
        Thread demo = new Thread(zy);
        System.out.println("Before the thread starts--->" + demo.isAlive());
        demo.start();
        System.out.println("After the thread starts--->" + demo.isAlive());
    }

- Execution results

Before the thread starts ---"false
 After the thread starts ---"true
Thread-0
Thread-0
Thread-0

  

The main thread may also end before the child thread ends.Subthreads are unaffected and do not end with the end of the main thread.

 

Five: Thread's mandatory join:

    

public class Zy implements Runnable{

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

    public static void main(String[] args) {
        Zy zy = new Zy();
        Thread demo = new Thread(zy,"thread");
        demo.start();
        for(int i=0;i<10;++i){
            if(i>5){
                try{
                    demo.join();  //Enforce demo
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main Thread Execution-->"+i);
        }
    }


}

  

Execution results

main thread execution-->0
 main thread execution-->1
 main thread execution-->2
 main thread execution-->3
 main thread execution-->4
 main thread execution-->5
 thread
 Thread//is forced before the main thread has finished
 thread
 main thread execution-->6
 main thread execution-->7
 main thread execution-->8
 main thread execution-->9

Six: Thread sleep:

public class Zy implements Runnable{

    public void run() {
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(2000);    //2000 2 seconds
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + i);
        }
    }

    public static void main(String[] args) {
        Zy zy = new Zy();
        Thread demo = new Thread(zy, "thread");
        demo.start();
    }


}

 

Execution results

Thread 0 
Thread 1
 Thread 2//Print one in less than two seconds

 

Seven, thread interrupt()

    

public class Zy implements Runnable{

    public void run() {
        System.out.println("implement run Method");
        try {
            Thread.sleep(10000);
            System.out.println("Thread Completes Sleep");
        } catch (Exception e) {
            System.out.println("Hibernation interrupted");
            return;  //Return to the call of the program
        }
        System.out.println("Thread terminated normally");
    }

    public static void main(String[] args) {
        Zy zy = new Zy();
        Thread demo = new Thread(zy, "thread");
        demo.start();
        try{
            Thread.sleep(2000);  
        }catch (Exception e) {
            e.printStackTrace();
        }
        demo.interrupt(); //2s Post-interrupt thread
    }
}

 

Execution results

Execute run method

--- Two seconds after interval

Hibernation interrupted

 

In a Java program, as long as one thread in the foreground is running, the entire Java program process will not disappear, so you can set a background thread at this time, so that even if the java process disappears, the background thread can continue to run.Main thread interrupt does not interrupt child threads

 

public class Zy implements Runnable{

    public void run() {
        while (true) {
            System.out.println(Thread.currentThread().getName() + "Running");
        }
    }

    public static void main(String[] args) {
        Zy zy = new Zy();
        Thread demo = new Thread(zy, "thread");
        demo.setDaemon(true);
        demo.start();
    }


}

 

Eight: Thread Priority

* View Thread Source Discovery

 /**
     * The minimum priority that a thread can have.  //Lowest
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;
    //The smaller the MIN_PRIORITY value, the lower the priority

 

public class Zy implements Runnable{

    public void run() {
        for(int i=0;i<5;++i){
            System.out.println(Thread.currentThread().getName()+"Function"+i);
        }
    }

    public static void main(String[] args) {
        Thread h1=new Thread(new Zy(),"A");
        Thread h2=new Thread(new Zy(),"B");
        Thread h3=new Thread(new Zy(),"C");
        h1.setPriority(8);
        h2.setPriority(2);
        h3.setPriority(6);
        h1.start();
        h2.start();
        h3.start();
    }


}

 

Printing effect

A Run 0
 A Run 1
 A Run 2
 A Run 3
 A Run 4
 C Run 0
 C Run 1
 C Run 2
 C Run 3
 C Run 4
 B Run 0
 B Run 1
 B Run 2
 B Run 3
 B Run 4

 

 

However, please do not mistake the reader for executing the higher priority.Who executes first or depends on who goes first to the CPU's resources, don't know if it is

The higher the value of NORM_PRIORITY, who gets the cpu resource first. I executed n times with the same result?

In addition, the priority of the main thread is 5.

Nine: Thread's gift.

In threaded operations, you can also use the yield() method to temporarily delegate operations from one thread to another.

public class Zy implements Runnable{

    public void run() {
        for(int i=0;i<5;++i) {
            System.out.println(Thread.currentThread().getName() + "Function" + i);
            if (i == 3) {
                System.out.println("Thread's gift");
                Thread.currentThread().yield();
            }
        }
    }

    public static void main(String[] args) {
        Thread h1=new Thread(new Zy(),"A");
        Thread h2=new Thread(new Zy(),"B");
        h1.start();
        h2.start();
    }


}

 

Execution effect

A Run 0
 A Run 1
 A Run 2
 A Run 3
 Thread's gift
 B Run 0
 B Run 1
 B Run 2
 B Run 3
 Thread's gift
 A Run 4
 B Run 4

 

 

10: Synchronization and deadlock.

      

public class Zy implements Runnable{
    private int count=5;
    public void run() {
        for(int i=0;i<10;++i){
            if(count>0){
                try{
                    Thread.sleep(1000);  //Take a second off
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(count--);
           }
        }
    }

    public static void main(String[] args) {
       Zy zy = new Zy();
        Thread h1=new Thread(zy);
        Thread h2=new Thread(zy);
        Thread h3=new Thread(zy);
        h1.start();
        h2.start();
        h3.start();
    }


}

 

Execution effect

5
3
4
2
2
2
1
0
-1

 

There should be a conflict between threads.

If you want to solve this problem, you need to use synchronization.Synchronization means that only one thread runs in a uniform period of time.

Other threads must wait until the end of this thread to continue execution.

[Synchronize code blocks]:

Grammar Format:

synchronized {

//Code requiring synchronization

}

public class Zy implements Runnable{
    private int count=5;
    public void run() {
        for(int i=0;i<10;++i){
            synchronized (this) {
                if (count > 0) {
                    try {
                        Thread.sleep(1000);  //Take a second off
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(count--);
                }
            }
        }
    }

    public static void main(String[] args) {
       Zy zy = new Zy();
        Thread h1=new Thread(zy);
        Thread h2=new Thread(zy);
        Thread h3=new Thread(zy);
        h1.start();
        h2.start();
        h3.start();
    }


}

 

results of enforcement

5
4
3
2
1
 //Output one in no seconds

 

 

[Synchronization method]

Synchronization can also be used.

Syntax format is synchronized method return type method name (parameter list){

// Other Code

}

public class Zy implements Runnable{
    private int count=5;
    public void run() {
        for (int i = 0; i < 10; ++i) {
            sale();
        }
    }
    public synchronized void sale() {
        if (count > 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(count--);
        }
    }

    public static void main(String[] args) {
       Zy zy = new Zy();
        Thread h1=new Thread(zy);
        Thread h2=new Thread(zy);
        Thread h3=new Thread(zy);
        h1.start();
        h2.start();
        h3.start();
    }


}

 

//The output is the same. Don't believe you can try it

 

deadlock

Synchronization is required when multiple threads share a resource, but too much synchronization can lead to deadlocks.

[Producer and consumer issues]

/*
*Public Information Class
*/
public class Info {
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    private String name = "Rollen";
    private int age = 20;
}

/**
*Consumer class
*/
public class Consumer implements Runnable {
    private Info info=null;
    public Consumer(Info info){
        this.info=info;
    }

    public void run(){
        for(int i=0;i<25;++i){
            try{
                Thread.sleep(100);
            }catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(this.info.getName()+"<---->"+this.info.getAge());
        }
    }
}
/**
*Production Class
*/
public class Producer implements Runnable {
    private Info info=null;
    Producer(Info info){
        this.info=info;
    }

    public void run(){
        boolean flag=false;
        for(int i=0;i<25;++i){
            if(flag){
                this.info.setName("Rollen");
                try{
                    Thread.sleep(100);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                this.info.setAge(20);
                flag=false;
            }else{
                this.info.setName("chunGe");
                try{
                    Thread.sleep(100);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                this.info.setAge(100);
                flag=true;
            }
        }
    }

}

 

Test Class

public static void main(String[] args) {

        Info info = new Info();
        Producer pro = new Producer(info);
        Consumer con = new Consumer(info);
        new Thread(pro).start();
        new Thread(con).start();

    }

 

 

test result

Rollen<---->100
chunGe<---->20
chunGe<---->100
Rollen<---->100
chunGe<---->20
chunGe<---->20
Rollen<---->100
Rollen<---->100
Rollen<---->100
chunGe<---->20
chunGe<---->100
chunGe<---->20
chunGe<---->20
chunGe<---->20
chunGe<---->100
Rollen<---->20
chunGe<---->100
Rollen<---->20
chunGe<---->100
chunGe<---->20
Rollen<---->100
chunGe<---->20
Rollen<---->100
Rollen<---->20
chunGe<---->20   //Name does not correspond to age

 

So how can I solve it?

1) Join Synchronization

2) Join Waiting and Waking

First, join synchronization

class Info {
     
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public synchronized void set(String name, int age){
        this.name=name;
        try{
            Thread.sleep(100);
        }catch (Exception e) {
            e.printStackTrace();
        }
        this.age=age;
    }
     
    public synchronized void get(){
        try{
            Thread.sleep(100);
        }catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(this.getName()+"<===>"+this.getAge());
    }
    private String name = "Rollen";
    private int age = 20;
}
 
/**
 * Producer
 * */
class Producer implements Runnable {
    private Info info = null;
 
    Producer(Info info) {
        this.info = info;
    }
 
    public void run() {
        boolean flag = false;
        for (int i = 0; i < 25; ++i) {
            if (flag) {
                 
                this.info.set("Rollen", 20);
                flag = false;
            } else {
                this.info.set("ChunGe", 100);
                flag = true;
            }
        }
    }
}
 
/**
 * Consumer class
 * */
class Consumer implements Runnable {
    private Info info = null;
 
    public Consumer(Info info) {
        this.info = info;
    }
 
    public void run() {
        for (int i = 0; i < 25; ++i) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
            this.info.get();
        }
    }
}
 
/**
 * Test Class
 * */
class hello {
    public static void main(String[] args) {
        Info info = new Info();
        Producer pro = new Producer(info);
        Consumer con = new Consumer(info);
        new Thread(pro).start();
        new Thread(con).start();
    }
}

 

Achieving results

Rollen<===>20
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100
ChunGe<===>100

 

Name and age correspond, but there is a problem with duplicate coverage

If you want to solve this problem, you need to use the Object class to help,

And we can use the wait and wake operations.

To do this, we only need to modify Info class hunger, add markers to it, and complete the wait and wake-up operations by judging the markers, as shown in the code below

public synchronized void set(String name, int age){
        if(!flag){
            try{
                super.wait();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        this.name=name;
        try{
            Thread.sleep(100);
        }catch (Exception e) {
            e.printStackTrace();
        }
        this.age=age;
        flag=false;
        super.notify();
    }
     
    public synchronized void get(){
        if(flag){
            try{
                super.wait();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
         
        try{
            Thread.sleep(100);
        }catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(this.getName()+"<===>"+this.getAge());
        flag=true;
        super.notify();
    }
    private String name = "Rollen";
    private int age = 20;
    private boolean flag=false;

 

 

Result

Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20
ChunGe<===>100
Rollen<===>20

 

Problem solving

Original address: http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html

 

 

 

 

 

 

 

 

 

 

Topics: Java jvm less