Java Multithreading Learning 1 (Getting Started) - The long-lost Java multithreading has finally come out!

1. Basic concepts

  • Program
    A program is an ordered collection of instructions and data
  • Process
    The process of executing a program
    Process is the unit of system resource allocation
  • Thread
    A process includes one or more threads. A thread
    is the unit of CPU scheduling and execution.
    Threads are executed independently.

Notice:

Multithreading refers to multiple CPU(ie multi-core) performing different tasks at the same time.

One can only execute one thread CPUon the same node

2. How to create a process

  1. inheritThread class
  2. accomplishRunnable interface
  3. accomplishCallable interface

Thread classAchievedRunnable interface

The JVM allows an application to execute multiple threads of execution concurrently

2.1 Priority of threads

Each thread has a priority

Higher priority threads execute before lower priority threads

The priority of the new thread is initially set to the priority of the creating thread

When a new thread is created within a thread, the new thread is a daemon thread if and only if the creating thread is a daemon process.

2.2 main thread stops

When the JVM starts, there is usually a non-daemon thread (usually calling a method mainnamed ). The JVM will continue executing the thread until one of the following occurs:

  • RuntimeThe method of the class has been called exit, and the security manager has allowed the exit operation
  • Total death of all non-daemon threads

2.3 Create a new thread

2.3.1 Thread

  1. inherit Threadclass
  2. rewriterun()
  3. main()method newof this class and callstart()
 /**
     * description: 线程学习
     * @author: Leet
     * @date: 2020-11-10 23:25
     **/
    public class TestThread1 extends Thread{
    
    
        
        @Override
        public void run() {
    
    
            for (int i = 0; i < 2000; i++) {
    
    
                System.out.println(String.format("%s%d", "我在看代码---", i));
            }
        }
    
        public static void main(String[] args) {
    
    
    
            new TestThread1().start();
    
            for (int i = 0; i < 2000; i++) {
    
    
                System.out.println(String.format("%s%d", "我在学习多线程---", i));
            }
        }
    }

2.3.2 Runnable

  1. accomplishRunnable
  2. rewriterun()
  3. main()In newone of this class is passed as a parameter to Threadthe object , callstart()
 /**
     * description: 多线程学习2
     *
     * @author: Leet
     * @date: 2020-11-10 23:39
     **/
    public class TestThread2 implements Runnable {
    
    
        @Override
        public void run() {
    
    
            for (int i = 0; i < 2000; i++) {
    
    
                System.out.println(String.format("%s%d", "我是天才-----", i));
            }
        }
    
        public static void main(String[] args) {
    
    
            new Thread(new TestThread2()).start();
    
            for (int i = 0; i < 2000; i++) {
    
    
                System.out.println(String.format("%s%d", "不,我才是天才-----", i));
            }
        }
    }

2.3.3 Callable

  1. accomplishCallable interface
  2. Override call()method , need to throw an exception
  3. Create target object XXX
  4. Create an execution service:ExecutorService es = Executors.newFixedThreadPool(1);
  5. Submit for execution:Future<Boolean> result = es.submit(XXX);
  6. Get the result:boolean r = result.get();
  7. Close the service:es.shutdown();

3. Static proxy mode

Both the real object and the proxy object implement the same interface

The proxy object proxies the real character

package proxy;

/**
 * description:静态代理学习
 *              通过“结婚”这个场景带入
 * @author Leet
 * @date 2020/11/11 9:31
 */
public interface Marry {
    
    
    void marry();
}

class You implements Marry {
    
    
    @Override
    public void marry() {
    
    
        System.out.println("今天我要结婚了,我很高兴");
    }
}

class WeddingCompany implements Marry {
    
    

    public WeddingCompany(Marry marrier) {
    
    
        this.marrier = marrier;
    }

    private Marry marrier;

    @Override
    public void marry() {
    
    
        before();
        marrier.marry();
        after();
    }

    private void before() {
    
    
        System.out.println("结婚前,婚庆公司布置现场");
    }

    private void after() {
    
    
        System.out.println("结婚后,婚庆公司打扫现场");
    }
}

class TestStaticProxy {
    
    
    public static void main(String[] args) {
    
    
        WeddingCompany weddingCompany = new WeddingCompany(new You());
        weddingCompany.marry();
    }
}

3.1 Proxy in Thread class

Thread 类Runnable interfaceProxy implementation class

4. lambda

  • Functional interface
    The interface has only one method

When using this interface to implement a class, you can use lambda

public class Main {
    
    
	public static void main(String[] args) {
    
    
		new Thread(() -> System.out.println("lambda 创建线程")).start();
	}
}

Lambda expressions are comfortable to use in stream programming of containers

5. Thread state

insert image description here
insert image description here

5.1 Thread method

setPriority(int newPriority) Change thread priority
static void sleep(long milis) Let the thread sleep for milis ms
void join() wait for the thread to terminate
static void yield() Suspend the thread and execute other threads (Let Yin)
isAlive() whether the thread is alive

5.1.1 Thread stop

  • Use a limited number of times to stop the thread
  • Use a flag(terminate loop) to let the thread stop
  • Do not use stop(), destory()(discarded)

5.1.2 Thread sleep

sleep()

Exceptions need to be caught:InterruptedException

sleep does not release the lock

After the insomnia time is reached, the thread enters the ready state

5.1.3 Thread politeness

yield()

Thread courtesy: Let the current thread stop, but not block, become ready

Courtesy doesn't necessarily mean success

5.1.4 join()

Merge threads, wait for this thread to finish executing, and then execute other threads (other threads are blocked at this time)

 /**
     * description: join() 方法测试
     * @author: Leet
     * @date: 2020-11-11 11:06
     **/
    public class TestJoin implements Runnable {
    
    
        @Override
        public void run() {
    
    
            for (int i = 0; i < 1000; i++) {
    
    
                System.out.printf("%s%d\n", "线程 VIP 来了 ---》 ", i);
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
    
    
            Thread thread = new Thread(new TestJoin());
            thread.start();
    
            for (int i = 0; i < 500; i++) {
    
    
                if (i == 200) {
    
    
                    thread.join();
                }
    
                System.out.printf("%s%d\n", "线程 main ---》 ", i);
            }
            // main :VIP 线程属实过分了,它自己执行那么多次,不老实排队,竟然利用自己的特权插队,这是可恶。
        }
    }

5.2 Observe thread status:Thread.State

5.3 Thread priority

Java provides priority for each thread

The thread scheduler decides which thread to schedule according to the priority

  • Priority just means the high or low probability of being scheduled
  • Thread priority: 1~10
  • get thread priority
    getPriority()
  • Set thread priority
    setPriority(int priority)

Suggestion: Priority is set start()before

   /**
     * description: 线程优先级测试
     *
     * @author: Leet
     * @date: 2020-11-11 11:26
     **/
    public class TestPriority implements Runnable {
    
    
        @Override
        public void run() {
    
    
            System.out.printf("%S 的 priority : %d\n", Thread.currentThread().getName(), Thread.currentThread().getPriority());
        }
    
        public static void main(String[] args) {
    
    
            System.out.printf("%S 的 priority : %d\n", Thread.currentThread().getName(), Thread.currentThread().getPriority());
    
            Thread thread1 = new Thread(new TestPriority(), "thread1");
            Thread thread2 = new Thread(new TestPriority(), "thread2");
            Thread thread3 = new Thread(new TestPriority(), "thread3");
            Thread thread4 = new Thread(new TestPriority(), "thread4");
            Thread thread5 = new Thread(new TestPriority(), "thread5");
    
            thread1.setPriority(1);
            thread2.setPriority(5);
            thread2.setPriority(9);
            thread4.setPriority(2);
            thread5.setPriority(10);
    
            thread1.start();
            thread2.start();
            thread3.start();
            thread4.start();
            thread5.start();
        }
    }

5.4 Daemon threads

  • setDaemon(true)Make this thread a daemon thread
  • The user thread ends, regardless of the daemon thread, and the JVM (program) stops
    /**
     * description: 守护线程
     * @author: Leet
     * @date: 2020-11-11 14:15
     **/
    public class TestDaemon {
    
    
        public static void main(String[] args) {
    
    
            Thread thread = new Thread(new God());
            thread.setDaemon(true);
            thread.start();
    
            new Thread(new You()).start();
        }
    }
    
    class God implements Runnable {
    
    
        @Override
        public void run() {
    
    
            while (true) {
    
    
                System.out.println("GOD BLESS YOU");
            }
            // 你到天堂,见到 GOD
            // GOD: 我还没反应过来,你咋就死了????!!!!!
        }
    }
    
    class You implements Runnable {
    
    
        @Override
        public void run() {
    
    
            for (int i = 0; i < 36500; i++) {
    
    
                System.out.println("You are happy every day");
            }
            System.out.println("----------Goodbye! The world----------");
        }
    }

6. Thread synchronization

6.1 Queues and locks

  • For a large number of unified resource access, you can use the queue
  • In order to solve access conflicts, when accessing, add a lock mechanism to synchronize
    a thread to obtain an exclusive lock on the object. This thread monopolizes the resource, and other threads must wait until the thread releases the lock.
    • existing problems
      1. Threads that have not acquired the lock are suspended
      2. Performance loss:
        • scheduling
        • priority

6.2 Unsafe example

  1. buy tickets
  2. withdraw money
  3. container

6.3 Synchronization method

By privateensuring that data can only be accessed by objects, synchronizedmechanisms are proposed for methods (acting on methods or blocks) to ensure synchronization.

For ordinary synchronization methods, the lock is the current instance object. If there are multiple instances, the lock objects must be different and synchronization cannot be completed.

For static synchronized methods, the lock is on the current class Class 对象. There are multiple instances, but the lock object is the same, and synchronization can be completed

For synchronized method blocks, the lock is a configuration object enclosed in synchronizedparentheses .

6.4 Deadlock

Multiple threads each occupy some shared resources, and wait for the resources occupied by other threads to run, resulting in a situation where two or more threads are waiting for each other to release resources and stop

When a synchronization block holds the locks of more than two objects at the same time, a "deadlock" problem may occur

package synchronizedtest.deadsynchronized;
    
    /**
     * description: 验证死锁
     *    死锁:多个线程互相持有各自需要的资源,而僵持
     *    synchronized 块同时持有两个以上对象的锁,就可能造成死锁
     *
     * @author: Leet
     * @date: 2020-11-11 15:25
     **/
    
    public class DeadLock {
    
    
        public static void main(String[] args) {
    
    
            // 灰姑娘想化妆,她拿起了口红
            new Thread(new Makeup(0, "灰姑娘")).start();
            // 白雪公主想化妆,她拿起了镜子
            new Thread(new Makeup(1, "白雪公主")).start();
        }
    }
    
    /**
     * 口红
     */
    class Lipstick {
    
    }
    
    /**
     * 镜子
     */
    class Mirror {
    
    }
    
    /**
     * 化妆
     */
    class Makeup implements Runnable {
    
    
    
        static Lipstick lipstick = new Lipstick();
        static Mirror mirror = new Mirror();
    
        int choice;
        String girlName;
    
        public Makeup(int choice, String girlName) {
    
    
            this.choice = choice;
            this.girlName = girlName;
        }
    
        @Override
        public void run() {
    
    
            try {
    
    
                makeup();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    
        /**
         * lipstick 与 mirror 是 Makeup 类的静态属性,为 Makeup 类对象持有;
         * lipstick 与 mirror只有一个,
         * 所以说,下方同步块中的代码,锁共享资源的方法正确
         */
        private void makeup() throws InterruptedException {
    
    
            if (choice == 0) {
    
    
                synchronized (lipstick) {
    
    
                    System.out.printf("%s 获得口红\n", girlName);
                    Thread.sleep(1000);
                }
                synchronized (mirror) {
    
    
                    System.out.printf("%s 获得镜子\n", girlName);
                }
            } else {
    
    
                synchronized (mirror) {
    
    
                    System.out.printf("%s 获得镜子\n", girlName);
                    Thread.sleep(2000);
                }
                synchronized (lipstick) {
    
    
                    System.out.printf("%s 获得口红\n", girlName);
                }
            }
        }
    }

7. Thread cooperation

What I learned before is that each thread does its own work, and it has nothing to do with each other and does not interfere with each other.

Now it's time to get the threads to work together!

7.1 Producer and consumer model

Producer and Consumer Problems

Assuming that only one product can be stored in the warehouse, the producer puts the produced product into the warehouse, and the consumer takes the product out of the warehouse for consumption

If there is no product in the warehouse, then the producer puts the product in the warehouse, otherwise stops production and waits until something in the warehouse is picked up by the consumer

If there is a product in the warehouse, then the consumer will take the product away for consumption, otherwise stop consuming and wait until there is a product in the warehouse again

This is a thread synchronization problem, the two share the same resource, depend on each other, and are mutually conditioned.

Obviously, just using synchronizedis not enough: synchronizedmessage passing between different threads cannot be achieved.

7.2 Thread communication

wait() Let the thread wait until notified by other threads without holding (releasing) the lock
wait(long timeout) Let the thread wait for the specified number of milliseconds
notify() Wake up a waiting thread
notifyAll() Wake up all threads that call the wait() method on the same class, and threads with higher priority are scheduled first

Note: They are all methods Object 类in and must be called in a synchronized block, otherwise throwIllegalMonitorStateException

7.3 Solutions

7.3.1 Tube method

Set a buffer with a certain capacity, the producer produces something into the buffer, and the consumer consumes from the buffer

Judging which thread to wake up and which thread to wait according to the state of the buffer capacity

    package thread.synchronize;
    
    /**
     * description: 生产者与消费者问题:管程法解决
     *
     * @author: Leet
     * @date: 2020-11-12 19:58
     **/
    public class TestPC {
    
    
        public static void main(String[] args) {
    
    
            SynContainer container = new SynContainer();
    
            new Productor(container).start();
            new Consumer(container).start();
        }
    }
    
    class Productor extends Thread {
    
    
        SynContainer container;
    
        public Productor(SynContainer container) {
    
    
            this.container = container;
        }
    
        @Override
        public void run() {
    
    
            for (int i = 0; i < 100; i++) {
    
    
                try {
    
    
                    container.push(new Chicken(i));
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.printf("生产了 %d 只鸡\n", i);
            }
        }
    }
    
    class Consumer extends Thread {
    
    
        SynContainer container;
    
        public Consumer(SynContainer container) {
    
    
            this.container = container;
        }
    
        @Override
        public void run() {
    
    
            for (int i = 0; i < 100; i++) {
    
    
                try {
    
    
                    System.out.printf("消费了---> %d 只鸡\n", container.pop().id);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
    
    class Chicken {
    
    
        int id;
    
        public Chicken(int id) {
    
    
            this.id = id;
        }
    }
    
    class SynContainer {
    
    
        Chicken[] chickens = new Chicken[10];
        int count = 0;
    
        /**
         * 生产者放入产品
         * @param chicken 产品
         * @throws InterruptedException InterruptedException
         */
        public synchronized void push(Chicken chicken) throws InterruptedException {
    
    
            // 如果容器满了,需要等待消费者消费
            if (count == chickens.length) {
    
    
                wait();
            } else {
    
    
                // 容器没满,生产者直接放入产品
                chickens[count++] = chicken;
    
                // 通知消费者消费
                notifyAll();
            }
        }
    
        /**
         * 消费者消费
         * @return Chicken Chicken
         * @throws InterruptedException InterruptedException 
         */
        public synchronized Chicken pop() throws InterruptedException {
    
    
            // 如果容器空了,消费者等待(等待生产者向容器中放入产品)
            if (count == 0) {
    
    
                this.wait();
            } {
    
    
                // 容器中有产品,消费者直接消费
                Chicken chicken = chickens[--count];
                
                // 告知生产者生产东西
                notifyAll();
    
                return chicken;
            }
        }
    }

7.3.2 Signal light method

Set an identifier, and judge which thread to wake up and which thread to wait according to the state of the identifier

    package thread.synchronize;
    
    /**
     * description: 生产者与消费者问题:信号灯法解决
     *
     * @author: Leet
     * @date: 2020-11-12 20:32
     **/
    public class TestPC2 {
    
    
        public static void main(String[] args) {
    
    
            TV tv = new TV();
            new Player(tv).start();
            new Watcher(tv).start();
        }
    }
    
    class Player extends Thread {
    
    
        TV tv;
    
        public Player(TV tv) {
    
    
            this.tv = tv;
        }
    
        @Override
        public void run() {
    
    
            for (int i = 0; i < 20; i++) {
    
    
                if (i % 2 == 0) {
    
    
                    this.tv.play("Hello World 播放中");
                } else {
    
    
                    this.tv.play("抖音:记录记录美好生活");
                }
            }
        }
    }
    
    class Watcher extends Thread {
    
    
        TV tv;
    
        public Watcher(TV tv) {
    
    
            this.tv = tv;
        }
    
        @Override
        public void run() {
    
    
            tv.watch();
        }
    }
    
    class TV {
    
    
        String voice;
    
        /**
         * true: 演员表演,观众等待
         * false: 观众观看,演员等待
         */
        boolean flag = true;
    
        public synchronized void play(String voice) {
    
    
            if (!flag) {
    
    
                try {
    
    
                    wait();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
    
            System.out.printf("演员表演了 %s\n", voice);
    
            notifyAll();
    
            this.voice = voice;
            this.flag = !this.flag;
        }
    
        public synchronized void watch() {
    
    
            if (flag) {
    
    
                try {
    
    
                    wait();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
    
            System.out.printf("观众观看了 %s\n", voice);
    
            notifyAll();
    
            this.flag = !this.flag;
        }
    }

This example is a bit flawed: it will deadlock.
Then please be smart and change it.

8. Thread pool

  • ExecutorService
    thread pool interface
    • void execute(Runnable command)
      Runnable 接口Execute implementation class
    • <T> Future <T> submit(Callable<T> task)
      Callable 接口Execute implementation class
    • void shutdown()
      Close the thread pool
  • Executor
    Factory classes for tool classes and thread pools
    are used to create and return different types of thread pools
   import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * description: 线程池
     *
     * @author: Leet
     * @date: 2020-11-12 20:57
     **/
    public class TestThreadPool implements Runnable{
    
    
        @Override
        public void run() {
    
    
            System.out.println(Thread.currentThread().getName());
        }
    
        public static void main(String[] args) {
    
    
            ExecutorService es = Executors.newFixedThreadPool(10);
    
            es.execute(new TestThreadPool());
            es.execute(new TestThreadPool());
            es.execute(new TestThreadPool());
            es.execute(new TestThreadPool());
    
            es.shutdown();
        }
    }



Guess you like

Origin blog.csdn.net/Snakehj/article/details/109657370