Multi-threaded study notes --- (basic knowledge)

Multi-threaded study notes --- (basic knowledge)

Simple understanding of processes and threads

A program is a collection of instructions, and a program is a process when it runs. The same program can have multiple processes. For example, qq can start multiple client programs to log in to different accounts. Process is the smallest unit of resource allocation. Thread is the smallest unit of cpu scheduling. Resources will not be shared between processes, otherwise one software will obtain the password of another software, and resources such as memory can be shared between threads.

3.ways to start multithreading

Thread
  • Get multi-threading capabilities by inheriting the Thread class
  • This class implements the Runnable interface and has a start method
  • Not recommended, there are limitations of OOP single inheritance
public class thread_test extends Thread{

    //
    //i-- 
    static int i=20;
    @Override
    public void run() {
        while (i>0){
            System.out.println(Thread.currentThread().getName()+": "+i--);
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        thread_test t1 = new thread_test();
        thread_test t2 = new thread_test();
        thread_test t3 = new thread_test();
        t1.start();
        t2.start();
        t3.start();
    }
}
 
Runnable
  • Implement the Runnable interface
  • Need to pass the interface implementation to new Thread() to obtain multi-threading capabilities, using a static proxy method
  • You can build an object and pass it to multiple new Threads to build multiple threads
  • It can avoid the limitation of single inheritance, it is recommended to use
public class Runnable_test implements Runnable{
    static int i = 20;
    @Override
    public void run() {
        while (i>0){
            System.out.println(Thread.currentThread().getName()+": "+i--);
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Runnable_test r1 = new Runnable_test();
//       Runnable_test r2 = new Runnable_test();
//       Runnable_test r3 = new Runnable_test();
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r1);
        Thread t3 = new Thread(r1);

        t1.start();
        t2.start();
        t3.start();
    }
}
 
Collable
  • Can have a return value
public class Callable_Test implements Callable<Boolean> {
    static int i = 20;
    @Override
    public Boolean call() throws Exception {
        while (i>0){
            System.out.println(Thread.currentThread().getName()+" : "+i--);
            Thread.sleep(20);
        }
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable_Test ct1 = new Callable_Test();
        Callable_Test ct2 = new Callable_Test();

        //
        ExecutorService es = Executors.newFixedThreadPool(3);

        Future<Boolean> s1 = es.submit(ct1);
        Future<Boolean> s2 = es.submit(ct2);

        Boolean b1 = s1.get();
        Boolean b2 = s2.get();

        es.shutdown();
        
    }
}
 

About Java generics

  • Since the Collable interface uses generics, I read the following blog post and thought it was written more carefully, first record it here, and then learn more when it is used more next time.
  • www.cnblogs.com/jingmoxukon...
  • If you use Object as the parameter type, although you can also pass in different objects, the generated object is equivalent to: Object o = new A(), you can only use the existing methods in object; but if you use generics, it is equivalent A a = new A(), it is more flexible to use

Static proxy

The proxy class and the proxy class must implement the same interface or inherit the same class, and override the same method. When you want to call the method of the proxy class, you can call the proxy class through the proxy class by calling the method of the proxy class with the same name. The method, usually a function addition and enhancement before and after the method is called

lambda expression

  • The interface with only one abstract method is a functional interface, and the implementation class of this interface can be expressed by lambda expressions
public class InnerClassTest {
    public static void main(String[] args) {
        saticInner saticInner = new saticInner();
        saticInner.run();

        //3. 
        class partInner implements innerRun{
            @Override
            public void run() {
                System.out.println("part inner class test");
            }
        }

        partInner partInner = new partInner();
        partInner.run();

        //4. 
        innerRun r = new innerRun() {
            @Override
            public void run() {
                System.out.println("anonymous class");
            }
        };
        r.run();

        //5.lambda 
        //
        //innerRun lanbdaTest = () -> {System.out.println("lambda 1");};
        //
        //innerRun lanbdaTest = () -> System.out.println("lambda 1");

        //
        //lambadTest lanbdaTest = (int a) -> {System.out.println(a);};

        //
        //
        lambadTest lanbdaTest =  a -> {System.out.println("lambda 1");};
    }

    //2. 
    static class  saticInner implements innerRun{
        @Override
        public void run() {
            System.out.println("static inner class test");
        }
    }
    

}

//1. 
class normalClass implements innerRun{
    @Override
    public void run() {
        System.out.println("normal class test");
    }
}


interface innerRun{
    void run();
}

interface lambadTest{
    void run0(int a);
}
 

Ways to stop the thread

  • It is generally not recommended to stop the thread through the stop, destroy and other methods that come with thread, and it is obsolete.
  • It is recommended to stop by setting the flag bit
public class stopThread implements Runnable{

    //
    boolean flag=true;
    int i = 0;

    @Override
    public void run() {
        //
        while (flag){
            System.out.println(i++);
        }
    }
    public void stop(){
        flag=false;
    }

    public static void main(String[] args) {
        stopThread st = new stopThread();
        Thread thread = new Thread(st);
        thread.start();
        for (int j =0 ;j<1000;j++){
            System.out.println("main"+j);
        }

        //flag false 
       st.stop();
    }
}
 

sleep--thread sleep

  • The network delay can be simulated by the thread.sleep() method
  • You can also count down
public class sleepTestr {
    public static void main(String[] args) {
        countDown();
    }

    public static void countDown(){
        for (int i = 10; i > 0; i--) {
            Date date = new Date(System.currentTimeMillis());
            System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
 

yield--thread politeness

  • Politeness is to let the thread from running to ready, let the CPU reallocation, but not necessarily successful, because it still depends on the CPU allocation
public class yieldTest implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" start");
        //Thread.yield();
        System.out.println(Thread.currentThread().getName()+" stop");
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new yieldTest());
        Thread t2 = new Thread(new yieldTest());
        t1.start();
        t2.start();

    }
}
 

join--thread forced execution

  • Let the join thread execute first
public class joinTest implements Runnable{
    @Override
    public void run() {
        for (int i = 100; i > 0; i--) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new joinTest());
        t1.start();
        for (int i = 200; i > 0; i--) {
            if (i==100){
                t1.join();
            }
            System.out.println("main"+i);
        }
    }
}
 

Thread state

  • thread.getState: Get the state of the thread

Thread priority

  • The priority of the main thread is the default
  • The priority must be set before the thread is started
  • The maximum thread priority is 10, the minimum is 1, and an error will be reported if it exceeds the range
  • The default value is 5, which means that the probability of getting the schedule is the same
  • High priority may not necessarily give priority to execution, it can only be said that the probability of priority is relatively high
public class priorityTest implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+": "+Thread.currentThread().getPriority());
    }

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getPriority());

        Thread t1 = new Thread(new priorityTest(), "t1");
        t1.setPriority(1);
        //
        t1.setDaemon(true);
        t1.start();

        Thread t2 = new Thread(new priorityTest(), "t2");
        t2.setPriority(7);
        t2.start();

        Thread t3 = new Thread(new priorityTest(), "t3");
        t3.setPriority(Thread.MAX_PRIORITY);
        t3.start();
    }
}
 

Daemon thread

  • The JVM virtual machine must ensure that the user thread is executed before it exits, but it does not have to wait for the daemon thread to finish executing
  • Background recording of operation logs, memory monitoring, garbage collection, etc. are all daemon threads
  • thread.seydaemon(true) means set as a daemon thread, the default value is false, which means that JVM can exit even if the thread is not finished running