Java multithreading (detailed notes)

introduction

It records the concept of multithreading, inheriting Thread, realizing Runnable, Thread sleep, Thread safety problems and solutions, multithread communication problems and Thread pool.

Overview of multithreading technology

Threads and processes

process

  • It refers to an application running in memory, and each process has an independent memory space

thread

  • It is an execution path in the process. It shares a memory space. Threads can switch freely and execute concurrently. A process has at least one thread.
  • Threads are actually further divided on the basis of processes. After a process is started, several execution paths in it can be divided into several threads.

Thread scheduling

Time sharing scheduling

  • All threads use the right to use the CUP in turn, and allocate the CPU time of each thread equally.

preemptive scheduling

  • Give priority to the threads with high priority to use CPU. If the threads have the same priority, one will be selected randomly (thread randomness). Java uses preemptive scheduling.

preemptive scheduling

  • The CPU uses preemptive scheduling mode to switch between multiple threads at high speed. For a core of the CPU, only one thread can be executed at a certain time, and the switching speed of the CPU between multiple threads is relatively faster than we think. It seems that it runs at the same time. In fact, multithreaded programs can not improve the running speed of the program, but can improve the running efficiency of the program and make the CPU utilization higher.

Synchronous and asynchronous

synchronization

  • Queuing execution is inefficient but safe.

asynchronous

  • At the same time, it is efficient but unsafe.

Concurrency and parallelism

Concurrent

  • Two or more things happen at the same time.

parallel

  • Two or more things happen at the same time.

Multithreading technology

Inherit Thread

Code example:

First write a sub Thread class to inherit Thread:

The code here is a new execution path

The trigger method of this execution path is not to directly call the run() method, but to start the task through the start () of the Thread object

package com.kkb.section5;

public class Thread1 extends Thread {
    //The run() method is the task method to be executed by the thread
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("***abed, I see a silver light***"+i);
        }
    }
}

Test class:

Program entry

package com.kkb.section5;

public class ThreadTest1 {
    public static void main(String[] args) {
        Thread1 t = new Thread1();
        t.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("---It's suspected to be frost on the ground---"+i);
        }
    }
}

Operation results:

analysis:

The result of each execution is different, because Java uses preemptive scheduling. When two threads execute, the execution is random.

Drawing analysis:

Each thread has its own stack space and shares a share of heap memory.
The method called by a thread will also be executed in this thread.

There is a simpler way to inherit Thread, which is implemented by using anonymous objects:

package com.kkb.section5;

public class RunnableTest2 {
    //Implement Runnable
    public static void main(String[] args) {
      	//Inherit the Thread through an anonymous object and execute the Thread
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println("Ten miles on the spring equinox is not as good as you"+i);
                }
            }
        }.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("Tianshan Mountain is like fire in August"+i);
        }
    }
}

Implement Runnable

Code example:

Write a task class to implement the Runnable interface:

package com.kkb.section5;

/**
 * A task used to execute a thread
 */
public class Runnable2 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("one two three four five"+i);
        }
    }
}

Program test:

package com.kkb.section5;

public class RunnableTest2 {
    //Implement Runnable
    public static void main(String[] args) {
        // 1. Create a task object
        Runnable2 r = new Runnable2();
        // 2. Create a thread and assign it a task
        Thread t = new Thread(r);
        // 3. Execution thread
        t.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("Go up the mountain to fight the tiger"+i);
        }
    }
}

Operation results:

analysis:

Compared with inheriting Thread, implementing Runnable has the following advantages:

  1. Multithreading is realized by creating tasks and then assigning them to threads, which is more suitable for multiple threads to execute the same task at the same time.
  2. It can avoid the limitations caused by single inheritance.
  3. The task is separated from the thread itself, which improves the robustness of the program.
  4. It is more conducive to the Thread pool technology, because the Thread pool receives Runnable type tasks and does not receive Thread type threads.

Thread class

  • A thread is a thread that executes in a program.

  • The Java virtual machine allows applications to run multiple execution threads at the same time.

  • Each thread has priority. The thread with higher priority takes precedence over the thread with lower priority.

  • There are two ways to create a new execution thread.

  1. One is to declare a class as a subclass of Thread. Then create the object of this class, assign the object to the Thread, and finally execute the Thread.
  2. The other is to implement and execute threads in anonymous objects.

Priority:

Variables and typesfielddescribe
static intMAX_PRIORITYThe maximum priority a thread can have.
static intMIN_PRIORITYThe lowest priority a thread can have.
static intNORM_PRIORITYThe default priority assigned to the thread.

Common construction methods:

constructor describe
Thread()Assign a new Thread object
Thread(Runnable target)Assign a new Thread object
Thread(Runnable target,String name)Assign a new Thread object and set a Thread name
Thread(String name)The name of the assignment thread

Common methods:

Variables and typesmethoddescribe
longgetId()Returns the identifier of this Thread.
StringgetName()Returns the name of this thread.
intgetPriority()Returns the priority of this thread.
voidsetPriority(int newPriority)Change the priority of this thread.
voidstart()This thread starts execution; The Java virtual machine calls the run method of this thread.
static voidsleep(long millis)The specified number of milliseconds that causes the currently executing thread to sleep (temporarily stop execution), depending on the accuracy and accuracy of the system timer and scheduler.
voidsetDaemon(boolean on)Mark this thread as a daemon thread or a user thread.
static ThreadcurrentThread()Returns a reference to the thread object currently executing.

Set and get thread name

package com.kkb.section5;

public class SetGetThreadName {
    public static void main(String[] args) {
        /**
         * Get thread name
         * currentThread()   Returns the current thread of execution
         * getName()    Returns the name of this thread.
         * getId()  Returns the identifier of this Thread.
         * getPriority()    Returns the priority of this thread.
         */
        System.out.println(Thread.currentThread().getName());//main
        System.out.println(Thread.currentThread().getId());//1
        System.out.println(Thread.currentThread().getPriority());//5
        /**
         * Set thread name
         * Method 1:
         */
        new Thread(new MyRunnable(),"Hey, hey, hey").start();
        /**
         * Method 2:
         */
        MyRunnable r = new MyRunnable();
        Thread t2 = new Thread(r,"Quack quack");
        t2.start();
        /**
         * Method 3:
         */
        Thread t3 = new Thread(new MyRunnable());
        t3.setName("rose");
        t3.start();
    }
    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
            System.out.println(Thread.currentThread().getId());
            System.out.println(Thread.currentThread().getPriority());
        }
    }
    
}

Thread sleep

package com.kkb.section5;

public class ThreadSleep {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            System.out.println("Hoe standing grain gradually pawning a midday"+i);
            Thread.sleep(1000);//1000ms=1s
        }
    }
}

Thread blocking

Thread blocking is not just thread hibernation.

A thread is a path. For example, a program has 100 lines of code. From line 1 to line 100, this is a complete path. If there are 10 lines of code in this program to read a file, you need to wait for 1 second when reading the file. This second is blocking.

In short, all time-consuming operations are blocked. Such as the time required to read the file, the time entered by the user, etc.

Thread interrupt

package com.kkb.section5;

public class ThreadSleep {
    public static void main(String[] args) throws InterruptedException {
        //Thread interrupt
        //A thread is an independent execution path. Whether it should end or not should be determined by itself
        Thread t = new Thread(new MyRunnable());
        t.start();
        for (int i = 0; i < 5; i++) {
            System.out.println("Hoe standing grain gradually pawning a midday"+i);
            Thread.sleep(1000);//1000ms=1s
        }
        //Give t thread
        t.interrupt();
    }

    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 8; i++) {
                System.out.println("Sweat drops under the grass"+i);
                try {
                    Thread.sleep(1000);//1000ms=1s
                } catch (InterruptedException e) {
//                    e.printStackTrace();
                    System.out.println("Discovery tag");
                    //With return, you can make the thread commit suicide
                    return;
                }
            }
        }
    }
}

Daemon thread

Threads are divided into guard threads and user threads

User thread: when a process does not contain any surviving user threads, it ends.

Daemon thread: it is used to guard user threads. When the last user thread ends, all daemon threads will die automatically.

(when not marked, it defaults to user thread)

voidsetDaemon(boolean on)Mark this thread as guard Thread or user thread.
package com.kkb.section5;

public class ThreadSetDeamon {
    public static void main(String[] args) throws InterruptedException {

        Thread t = new Thread(new MyRunnable());
        //Set t as the daemon thread, and enter true to indicate
        t.setDaemon(true);
        t.start();
        for (int i = 1; i <= 5; i++) {
            System.out.println("Hoe standing grain gradually pawning a midday"+i);
            Thread.sleep(1000);//1000ms=1s
        }
    }

    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i = 1; i < 10; i++) {
                System.out.println("Sweat drops under the grass"+i);
                try {
                    Thread.sleep(1000);//1000ms=1s
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Thread insecurity

Observe the following code:

package com.kkb.section5.thread_safety;

public class SafetyProblem {
    public static void main(String[] args) {
        Runnable run = new Ticket();//Using polymorphism to create objects
        new Thread(run).start();
        new Thread(run).start();
        new Thread(run).start();
    }
    //Selling tickets
    static class Ticket implements Runnable{
        private int count = 10;//Number of votes
        @Override
        public void run() {
            while(count>0){
                //Selling tickets
                System.out.println("Tickets are being issued...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println("The ticket has been issued successfully. At present, the remaining tickets are:"+count);
            }
        }
    }
}

Operation results:

analysis:

Since multiple threads operate on a data count at the same time, there is an interval between the judgment of entering the while loop and count -. In this interval, other threads will step in and execute, so the data is modified many times in the while loop. You can see that there is a negative number in the last face ticket number, which is obviously illogical. This is a thread unsafe problem.

So how to solve this problem?

Here are three methods.
Synchronization code block, synchronization method and display Lock

Thread safe 1-synchronous code block

Solution: when entering the while loop, threads cannot be allowed to participate in the execution, and each thread is executed according to the queue.

package com.kkb.section5.thread_safety;

public class SafetyProblem1 {
    /**
     * Thread synchronization: synchronized
     *      Solution 1: synchronize code blocks
     *           Format: synchronized (lock object){
     *                       //Lock object: any object can be used as a lock object
     *                    }
     * @param args
     */
    public static void main(String[] args) {
        Runnable run = new Ticket();//Using polymorphism to create objects
        new Thread(run,"Window 1:").start();
        new Thread(run,"Window 2:").start();
        new Thread(run,"Window 3:").start();
    }
    //Selling tickets
    static class Ticket implements Runnable{
        private int count = 10;//Number of votes
        private Object o = new Object();
        @Override
        public void run() {
            while(true){
                //Here, Object is used as the lock Object
                synchronized(o) {
                    if (count > 0) {
                        //Selling tickets
                        System.out.println("Tickets are being issued...");
                        try {
                            Thread.sleep(800);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        count--;
                        System.out.println(Thread.currentThread().getName()+"The ticket has been issued successfully. At present, the remaining tickets are:" + count);
                    }else {
                        break;
                    }
                }
            }
        }
    }
}

Operation screenshot:

analysis:

When selling tickets, the three threads must use the same lock to queue up. If it is not the same lock and each thread has its own lock, the previous thread unsafe problem will occur. The results show that all the tickets have been issued. No matter how they are operated, there are 10 tickets. Although all the lock objects can solve the problem of thread insecurity, the execution efficiency is slow.

Thread safe 2- synchronization method

package com.kkb.section5.thread_safety;

public class SafetyProblem2 {
    /**
     * Thread synchronization: synchronized
     *      Solution 2: synchronization method
     *           Format (example): public synchronized void method name () {}
     * @param args
     */
    public static void main(String[] args) {
        Runnable run = new Ticket();//Using polymorphism to create objects
        new Thread(run,"Window 1:").start();
        new Thread(run,"Window 2:").start();
        new Thread(run,"Window 3:").start();
    }
    //Selling tickets
    static class Ticket implements Runnable{
        private int count = 10;//Number of votes
        private Object o = new Object();
        @Override
        public void run() {
            while(true){
                boolean flag = sale();
                 if (!flag) {
                    break;
                }
            }
        }
        public synchronized boolean sale(){
            if (count > 0) {
                //Selling tickets
                System.out.println("Tickets are being issued...");
                try {
                    Thread.sleep(800);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println(Thread.currentThread().getName()+"The ticket has been issued successfully. At present, the remaining tickets are:" + count);
                return true;
            }
            return false;
        }
    }
}

Thread safe 3- explicit Lock

package com.kkb.section5.thread_safety;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SafetyProblem3 {
    /**
     * Both synchronized code blocks and synchronized methods are implicit locks
     *      Solution 3: display Lock
     *              Lock Subclass ReentrantLock
     * @param args
     */
    public static void main(String[] args) {

        Runnable run = new Ticket();//Using polymorphism to create objects
        new Thread(run,"Window 1:").start();
        new Thread(run,"Window 2:").start();
        new Thread(run,"Window 3:").start();
    }
    //Selling tickets
    static class Ticket implements Runnable{
        private int count = 10;//Number of votes
        //Explicit lock l
        private Lock l = new ReentrantLock();
        private Object o = new Object();
        @Override
        public void run() {
            while(true){
                //lock up
                l.lock();
                if (count > 0) {
                    //Selling tickets
                    System.out.println("Tickets are being issued...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count--;
                    System.out.println(Thread.currentThread().getName()+"The ticket has been issued successfully. At present, the remaining tickets are:" + count);

                }else {
                    break;
                }
                l.unlock();//Unlock
            }
        }
    }
}

analysis:

Display lock is better than implicit lock, which can better reflect the concept of lock and our programmers' control of lock in the development program. They can create locks, control locking and control unlocking. Lock object can better reflect the object-oriented mechanism.

Difference between implicit lock and display lock:

differenceImplicit lock synchronizedShow Lock lock
Different levelsIs a JVM level lockIt is an API level lock
Different ways of useAutomatically acquire and release locksManually acquire and release locks
Is waiting interruptibleNon interruptibleCan interrupt
Whether fair lock can be setCan only be a non fair lockBoth are allowed. The default is non fair lock
A lock binds multiple conditions to a conditionThe thread cannot be awakened preciselyCan accurately wake up the thread
Performance differenceLow performanceHigh performance

Fair lock and unfair lock

Fair lock: multiple threads obtain locks in the order of applying for locks. Threads will directly enter the queue to queue. They will always be the first in the queue to obtain locks.

  • Advantages: all threads can get resources and will not starve to death in the queue.
  • Disadvantages: the efficiency will decrease. Except for the first thread in the queue, other threads will cause blocking, and the overhead of CPU wake-up thread blocking will increase.

Unfair lock: all threads grab the first position of the lock, and they will get it directly. If they get it, they will get the lock directly. If they can't get it, they will go to the queue and wait for the next time.

  • Advantages: it can reduce the overhead of CPU waking up threads, and the overall efficiency is high. The CPU does not need to wake up all threads.
  • Disadvantages: it may cause some threads to fail to acquire locks for a long time or starve to death in the queue.

thread deadlock

package com.kkb.section5.thread_safety;

public class DealLock {
    public static void main(String[] args) {
        Culprit c = new Culprit();
        Police p = new Police();
        new MyThread(c,p).start();
        c.say(p);
    }
    static class MyThread extends Thread{
        private Culprit c;
        private Police p;
        public MyThread(Culprit c,Police p){
            this.c = c;
            this.p = p;
        }
        @Override
        public void run() {
            p.say(c);
        }
    }
    static class Culprit{
        public synchronized void say(Police p){
            System.out.println("Criminal: you let me go, I let the hostages go");
            p.fun();
        }
        public synchronized void fun(){
            System.out.println("The criminal was caught");
        }
    }
    static class Police{
        public synchronized void say(Culprit c){
            System.out.println("Policeman: you released the hostage, I released you");
            c.fun();
        }
        public synchronized void fun(){
            System.out.println("The police rescued the hostages and captured the criminals");
        }
    }
}

There are two kinds of operation results: 1 Thread deadlock; 2. Normal operation.

Thread deadlock:

Normal operation:

terms of settlement:

From the root cause, it is possible to generate a lock. Do not call the method that may generate a lock.

Multi thread communication problem

Producer and Consumer

package com.kkb.section5;

public class Demo {
    public static void main(String[] args) {
        Food f = new Food();
        new Chef(f).start();
        new Waiter(f).start();
    }
    //cook
    static class Chef extends Thread{
        private Food f;
        public Chef(Food f) {
            this.f = f;
        }
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                if (i%2==0) {
                    f.setFood("braised prawns ", "Spicy");
                }else {
                    f.setFood("Preserved egg salad","Cool and slightly spicy");
                }
            }
        }
    }
    //waiter
    static class Waiter extends Thread{
        private Food f;
        public Waiter(Food f) {
            this.f = f;
        }

        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                f.getFood();
            }
        }
    }
    //food
    static class Food{
        private String name;//Dish name
        private String taste;//taste
        //true means it can be produced
        private boolean flag = true;
        public synchronized void setFood(String name, String taste){
            if (flag) {
                this.name = name;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.taste = taste;
                flag = false;
                //Wake up all threads
                this.notifyAll();
                //This thread is interrupted and waits for other threads to wake up
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        public synchronized void getFood(){
            // If the flag is false, take the food
            if (!flag) {
                System.out.println("The name of the dish served by the waiter is: " + name + ",The taste is:" + taste);
                flag = true;
                //Wake up all threads
                this.notifyAll();
                //This thread is interrupted and waits for other threads to wake up
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Operation screenshot:

Six states of threads

  • Thread status. A thread can be in one of the following states:
    • NEW
      Threads that have not been started are in this state.
    • RUNNABLE
      The thread executing in the Java virtual machine is in this state.
    • BLOCKED
      Threads that are blocked waiting for a monitor lock are in this state.
    • WAITING
      A thread that waits indefinitely for another thread to perform a specific operation is in this state.
    • TIMED_WAITING
      The thread that is waiting for another thread to perform an operation with the maximum specified wait time is in this state.
    • TERMINATED
      The exited thread is in this state.

Understand the six states of threads by drawing:

Thread Callable with return value

The Callalble interface supports the return of execution results, and futuretask.com needs to be called Get (), this method will block the main process from continuing to execute. If it is not called, it will not block.

package com.kkb.section5;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Callable1 {
    /**
     * Thread Callable with return value
     * @param args
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> c = new MyCallable();
        FutureTask<Integer> task = new FutureTask(c);
        new Thread(task).start();
        //Let the Callable thread get the return value before executing the main thread
        Integer k = task.get();
        System.out.println("The return value is:"+k);

        for (int i = 0; i < 5; i++) {
            System.out.println("Watermelon:"+i);
        }
    }
    //Create a MyCallable class to implement the Callable interface
    static class MyCallable implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {
            for (int i = 0; i < 5; i++) {
                System.out.println("potato:"+i);
            }
            return 100;
        }
    }
}

Operation results:

The difference between Runnable and Callable:

  • Similarities:
  1. All interfaces
  2. Can write multithreaded programs
  3. Thread Start() starts the thread
  • difference
  1. Runnable has no return value; Callable can return execution results
  2. call() of the Callable interface allows exceptions to be thrown;
  3. run() of Runnable cannot be thrown

Thread pool

Thread pool concept

Thread pool Executors

If there are a large number of concurrent threads and each thread executes a task for a short time, the efficiency of the system will be greatly reduced because it takes time to create and destroy threads frequently Thread pool is a container that holds multiple threads. Threads in the pool can be used repeatedly, eliminating the operation of frequently creating thread objects and saving a lot of time and resources.

Advantages of thread pool

  • Reduce resource consumption
  • Improve response speed
  • Improve thread manageability

There are four thread pools in Java ExecutorService

  1. Cache thread pool
  2. Fixed length linear pool
  3. Single thread pool
  4. Periodic task fixed length routing pool

Cache thread pool

The length of the cache thread pool is unlimited.

package com.kkb.section5.threadpool;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class ThreadPool01 {
    /**
     * Cache thread pool
     * Execution process after adding a task:
     *      1. Determine whether there are idle threads in the thread pool
     *      2. Use if present
     *      3. If it does not exist, create a thread, put it into the thread pool, and then use
     */
    public static void main(String[] args) {
        //Create cache pool object
        ExecutorService service = Executors.newCachedThreadPool();
        //Directs the execution of new tasks in the thread pool
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Potato potato");
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Potato potato");
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Potato potato");
            }
        });
        //After the main thread sleeps for 1s, it will select a random idle thread in the thread pool
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Watermelon watermelon");
            }
        });
    }
}

Fixed length linear pool

The thread pool length is the specified value.

package com.kkb.section5.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPool02 {
    /**
     * Fixed length linear pool
     *   (Length is specified)
     * Execution process after adding a task:
     *      1. Determine whether there are idle threads in the thread pool
     *      2. Use if present
     *      3. If there is no idle thread and the thread pool is not full, create a thread and put it into the thread pool, and then use
     *      4. When there are no idle threads and the thread pool is full, wait for idle threads in the thread pool
     */
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(3);
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Hey, hey, hey");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Hey, hey, hey");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Hey, hey, hey");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Ha ha ha");
            }
        });

    }
}

Single thread pool

package com.kkb.section5.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPool03 {
    /**
     *  Single thread pool
     *  Execution process:
     *          1. Judge whether the thread pool is empty
     *          2. Use this thread when idle
     *          3. If it is not idle, wait until a single thread pool in the thread pool is idle
     */
    public static void main(String[] args) {
        ExecutorService service = Executors.newSingleThreadExecutor();
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"abed, I see a silver light");
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"abed, I see a silver light");
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"abed, I see a silver light");
            }
        });
    }
}

Periodic task fixed length routing pool

package com.kkb.section5.threadpool;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPool04 {
    /**
     * Periodic task fixed length routing pool
     * Execution process:
     *      1. Determine whether there are idle threads in the thread pool
     *      2. Use if present
     *      3. If there is no idle thread and the thread pool is not full, create a thread and put it into the thread pool, and then use
     *      4. When there are no idle threads and the thread pool is full, wait for idle threads in the thread pool
     *
     * When a recurring task is executed:
     *          Execute regularly. When an opportunity is triggered, a task will be automatically executed
     */
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
        /**
         * Type I: regular execution once
         *  Parameter 1 Scheduled tasks
         *  Parameter 2 Duration number
         *  Parameter 3 The time unit of the duration number, TimeUnit Constant assignment
         */
        System.out.println("Execute once in 2 seconds....");
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("Alone");
                System.out.println("3 Execute periodically for 1 second after 2 seconds");
            }

        },2, TimeUnit.SECONDS);

        /**
         * Type 2: periodic execution of tasks
         * Parameter 1 task
         * Parameter 2 Delay duration number (after when is the first execution)
         * Parameter 3 Cycle duration number (how often each cycle is executed)
         * Parameter 4. Unit of duration number
         */

        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Hoe standing grain gradually pawning a midday");
            }
        },3,1,TimeUnit.SECONDS);
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"Sweat drops under the grass");
            }
        },3,1,TimeUnit.SECONDS);

    }
}

summary

For multithreading technology:

  1. Convenient communication and data exchange
  2. More efficient use of CPU
  3. Using threads, you can put tasks in programs that occupy a long time in the background.
  4. The running efficiency of the program is accelerated.
  5. In the implementation of some waiting tasks, such as user input, file reading and writing, threads are more useful. In this case, some memory occupation can be released.
  6. If there are a large number of threads, it will affect performance.
  7. The more threads, the more memory space is required.
  8. Threads may bring more "bug s" to the program, so use them with caution.
  9. Thread termination needs to consider its impact on program operation.
  10. Generally, block model data is shared among multiple threads, so thread deadlock needs to be prevented.

Keywords: Java Multithreading JavaSE

Added by MrKaraokeSteve on Thu, 23 Dec 2021 20:31:10 +0200