Java learning path: day19 multithreading 2

Article catalog

All source code: https://github.com/name365/JavaSE-30Day

Reprinted from atguigu.com video

Chapter 8 multithreading

Thread life cycle

  • Used in JDK Thread.State Class defines several states of a thread

    To implement multithreading, a new Thread object must be created in the main Thread. The Java language uses the objects of Thread class and its subclasses to represent threads. In a complete life cycle, threads usually experience the following five states:

    • New: when an object of a Thread class or its subclass is declared and created, the new Thread object is in the new state
    • Ready: after the new thread is started (), it will enter the thread queue to wait for the CPU time slice. At this time, it has the conditions to run, but it is not allocated to the CPU resources
    • Run: when a ready thread is scheduled and gets CPU resources, it enters the run state. The run() method defines the operation and function of the thread
    • Blocking: in some special case, when the input and output operations are suspended or executed by human, the CPU is released and its execution is temporarily suspended, and it enters the blocking state
    • Death: the thread has completed all its work or the thread is forced to terminate in advance or an exception occurs, resulting in the end
  • Thread life cycle

Synchronization of threads

Questions raised

The uncertainty of multi thread execution causes the instability of execution results

The sharing of ledgers by multiple threads will result in incomplete operations and damage data.

  • Example: simulate the ticket selling procedure of railway station, open three windows to sell tickets.
class Windows1 implements Runnable{

    private int ticket = 100;

    @Override
    public void run() {
        while(true){
            if(ticket > 0){
                System.out.println(Thread.currentThread().getName() + ":Ticket No: " + ticket);
                ticket--;
            }else{
                break;
            }
        }
    }
}

public class WindowsTest1 {
    public static void main(String[] args) {
        Windows1 w = new Windows1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}
  • Ideal state

  • Extreme state

Thread safety problem of implementing Runnable by synchronous code block processing

/**
 *  Example: create three windows to sell tickets. The total number of tickets is 100. Use the method to implement the Runnable interface
 *  1.In the process of selling tickets, there are two problems: duplicate tickets and wrong tickets --- thread safety
 *  2.Cause of the problem: when a thread is operating the ticket, and the operation is not completed, other threads participate in and operate the ticket
 *  3.How to solve: when one thread is operating ticket, other threads cannot participate. Until thread a finishes ticket operation, others
 *            Thread can operate ticket. This situation cannot be changed even if thread a is blocked.
 *  4.In java, we use synchronization mechanism to solve the thread security problem.
 *
 *  Mode 1: synchronize code blocks
 *  synchronized(Sync monitor){
 *      //Code to be synchronized
 *
 *  }
 *  Note: 1. The code for operating shared data, that is, the code to be synchronized must not contain more code or less code.
 *       2.Shared data: variables operated by multiple threads. For example, ticket is to share data
 *       3.Synchronous monitor, commonly known as lock. Any object of a class can act as a lock.
 *          Requirement: multiple threads must share the same lock.
 *
 *       Add: in the way of implementing the Runnable interface to create multi threads, we can consider using this as the synchronization monitor.
 *
 *  Mode 2: synchronization method
 *      If the code that operates the shared data is fully declared in a method, we might as well synchronize this method declaration with the
 *
 *  5.The method of synchronization solves the problem of thread safety. ---Benefits
 *    When operating the synchronization code, only one thread can participate and other threads wait. It is a single thread process with low efficiency. ---Limitations
 *
 * @author subei
 * @create 2020-05-07 18:52
 */

class Windows1 implements Runnable{

    private int ticket = 100;
//    Object obj = new Object();
//    Dog dog = new Dog();

    @Override
    public void run() {
        while(true){
            synchronized (this) {//this: the only object of windows1 / / mode 2: synchronized (dog){
                if (ticket > 0) {

                    try{
                        Thread.sleep(100);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":Ticket No: " + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowsTest1 {
    public static void main(String[] args) {
        Windows1 w = new Windows1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}
class Dog{

}
  • Analysis of synchronization principle

Synchronous code block processing Thread safety problem of inheriting Thread class

/**
 * Using synchronous code block to solve the Thread safety problem of inheriting Thread class
 *
 * Example: create three c windows to sell tickets. The total number of tickets is 100
 *
 *
 *
 * @author subei
 * @create 2020-05-08 11:32
 */
class Windows extends Thread{

    private static int ticket = 100;
    private static Object obj = new Object();

    @Override
    public void run() {
        while(true){
            //correct
//            synchronized (obj) {
            synchronized (Windows.class){   //Class clazz = Windows.class
            //Wrong, because this represents three objects T1, T2 and T3 at this time
//            synchronized (this) {
                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(getName() + ":Ticket No: " + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowsTest2 {
    public static void main(String[] args) {
        Windows t1 = new Windows();
        Windows t2 = new Windows();
        Windows t3 = new Windows();

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

Synchronous method to deal with thread safety of Runnable

/**
 * Using synchronous method to solve the thread safety problem of implementing Runnable interface
 *
 * Summary of synchronization methods:
 *  1. The synchronization method still involves the synchronization monitor, but we don't need to explicitly declare it.
 *  2. Non static synchronization method, the synchronization monitor is: this
 *     The static synchronization method, the synchronization monitor is: the current class itself
 *
 * @author subei
 * @create 2020-05-08 14:27
 */

class Windows3 implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    public synchronized void show() { //Synchronization monitor: this
//        synchronized (this){
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":Ticket No: " + ticket);
                ticket--;
            }
//        }
    }
}

public class WindowsTest3 {
    public static void main(String[] args) {
        Windows3 w3 = new Windows3();

        Thread t1 = new Thread(w3);
        Thread t2 = new Thread(w3);
        Thread t3 = new Thread(w3);

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

Synchronous method to deal with Thread safety problem of inheriting Thread class

/**
 * Thread safety in the way of inheriting thread class by using synchronous method
 *
 * @author subei
 * @create 2020-05-08 14:42
 */

class Windows4 extends Thread {


    private static int ticket = 100;

    @Override
    public void run() {

        while (true) {

            show();
        }

    }
    private static synchronized void show(){//Synchronization monitor: Window4.class
        //private synchronized void show() {/ / synchronization monitor: t1,t2,t3. This solution is wrong
        if (ticket > 0) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + ": Ticket number:" + ticket);
            ticket--;
        }
    }
}


public class WindowsTest4 {
    public static void main(String[] args) {
        Windows4 t1 = new Windows4();
        Windows4 t2 = new Windows4();
        Windows4 t3 = new Windows4();


        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();

    }
}

Lazy mode of thread safe singleton

/**
 * Using synchronization mechanism to change the lazy style in singleton mode to thread safe
 *
 * @author subei
 * @create 2020-05-08 16:57
 */
public class BankTest {
}
class Bank{

    private Bank(){}

    private static Bank instance = null;

    public static Bank getInstance(){
        //Mode 1: slightly inefficient
        //Shortcut: Alt+Shift+Z
//        synchronized (Bank.class) {
//            if(instance == null){
//                instance = new Bank();
//            }
//            return instance;
//        }

        //Mode 2: high efficiency
        if(instance == null) {
            synchronized (Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }
            }
        }
        return instance;
    }
}

Deadlock problem

  • Example 1
/**
 * Demonstrate thread deadlock
 *
 * 1.Understanding of Deadlock: different threads occupy the synchronization resources needed by each other without giving up,
 *       They are waiting for the other party to give up the synchronization resources they need, forming a thread deadlock
 * 2.explain:
 *      >After deadlock, no exception and prompt will appear, but all threads are blocked and cannot continue
 *      >When we use synchronization, we should avoid deadlock.
 *
 * @author subei
 * @create 2020-05-08 17:25
 */
public class ThreadTest {
    public static void main(String[] args) {

        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();

        new Thread(){
            @Override
            public void run() {

                synchronized (s1){
                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}
  • Example 2
class A {
	public synchronized void foo(B b) {
		System.out.println("Current thread name: " + Thread.currentThread().getName()
				+ " In A Instance's foo method"); // ①
		try {
			Thread.sleep(200);
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
		System.out.println("Current thread name: " + Thread.currentThread().getName()
				+ " Attempt to call B Instance's last method"); // ③
		b.last();
	}

	public synchronized void last() {
		System.out.println("In A Class last Method internal");
	}
}

class B {
	public synchronized void bar(A a) {
		System.out.println("Current thread name: " + Thread.currentThread().getName()
				+ " In B Instance's bar method"); // ②
		try {
			Thread.sleep(200);
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
		System.out.println("Current thread name: " + Thread.currentThread().getName()
				+ " Attempt to call A Instance's last method"); // ④
		a.last();
	}

	public synchronized void last() {
		System.out.println("In B Class last Method internal");
	}
}

public class DeadLock implements Runnable {
	A a = new A();
	B b = new B();

	public void init() {
		Thread.currentThread().setName("Main thread");
		// Call foo method of a object
		a.foo(b);
		System.out.println("After entering the main thread");
	}

	public void run() {
		Thread.currentThread().setName("Subthread");
		// Calling bar method of b object
		b.bar(a);
		System.out.println("After entering the sub thread");
	}

	public static void main(String[] args) {
		DeadLock dl = new DeadLock();
		new Thread(dl).start();
		dl.init();
	}
}

Lock mode to solve thread safety problems

  • java.util.concurrent.locks.Lock Interface is a tool for controlling multiple threads to access shared resources. Lock provides exclusive access to shared resources. Only one thread can lock lock the lock object at a time. The thread should obtain the lock object before accessing shared resources.
  • ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. In the control of thread safety, ReentrantLock is more commonly used, which can explicitly Lock and release locks.
  • Starting with JDK 5.0, Java provides a more powerful thread synchronization mechanism - synchronization is achieved by explicitly defining synchronization Lock objects. The Lock object is used as the synchronization Lock.
import java.util.concurrent.locks.ReentrantLock;

/**
 * Three ways to solve the thread safety problem: lock lock -- JDK 5.0 NEW
 *
 * Note: if there is an exception in the synchronization code, write unlock() to the finally statement block
 *
 * 1. Interview question: the similarities and differences between synchronized and Lock?
 *    Same: both can solve thread safety problems
 *    Different: the synchronized mechanism automatically releases the synchronization monitor after executing the corresponding synchronization code
 *         Lock You need to start the synchronization manually (lock()), and end the synchronization manually (unlock())
 *
 * 2.Priority:
 *      Lock Synchronization code block (has entered method body and allocated corresponding resources)  synchronization method (outside method body)
 *
 * Interview question: how to solve the thread safety problem? There are several ways
 *
 * @author subei
 * @create 2020-05-08 17:49
 */

class Windows implements Runnable{

    private int ticket = 100;
    //1. Instantiate ReentrantLock
    private ReentrantLock lock = new ReentrantLock();


    @Override
    public void run() {
        while(true){
            try{

                //Call lock method: lock()
                lock.lock();

                if(ticket > 0){

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":Ticket No: " + ticket);
                    ticket --;
                }else{
                    break;
                }
            }finally {
                //3. Call unlocking method: unlock()
                lock.unlock();
            }
        }
    }
}

public class LockTest {
    public static void main(String[] args) {
        Windows w = new Windows();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}
  • practice
/**
 * The bank has an account.
 * There are two depositors who deposit 3000 yuan into the same account, 1000 yuan each time, three times.
 * Print the account balance after each deposit.
 *
 * analysis:
 *      1.Is it a multi-threaded problem? Yes, two savers threads
 *      2.Is there shared data? Yes, account (or account balance)
 *      3.Is there a thread safety issue? Yes
 *      4.Need to consider how to solve the thread safety problem? Synchronization mechanism: there are three ways.
 *
 * @author subei
 * @create 2020-05-08 18:23
 */
class Account{
    private double balance;

    public Account(double balance){
        this.balance = balance;
    }

    //save money
    public synchronized void deposit(double amt){
        if(amt > 0){

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            balance += amt;
            System.out.println(Thread.currentThread().getName() + ":" + "Deposit succeeded, current balance:" + balance);
        }
    }
}

class Customer extends Thread{

    private Account acct;
    public Customer(Account acct){
        this.acct = acct;
    }

    @Override
    public void run() {

        for(int i = 0;i < 3;i++){
            acct.deposit(1000);
        }
    }
}

public class AccountTest {
    public static void main(String[] args) {
        Account acct = new Account(0);
        Customer c1 = new Customer(acct);
        Customer c2 = new Customer(acct);

        c1.setName("nail");
        c2.setName("B");

        c1.start();
        c2.start();
    }
}

Thread communication

/**
 * Example of thread communication: print 1-100 with two threads. Thread 1, thread 2 alternate print
 *
 * Three methods are involved:
 * wait():Once this method is executed, the current thread enters a blocked state and releases the synchronization monitor.
 * notify():Once this method is executed, it wakes up a thread that is waiting. If more than one thread is waiting, wake up the higher priority one.
 * notifyAll():Once this method is executed, all threads that are wait ing will wake up.
 *
 * explain:
 *      1.wait(),notify(),notifyAll()Three methods must be used in a synchronization block or synchronization method.
 *      2.wait(),notify(),notifyAll()The caller of the three methods must be a synchronization block or a synchronization monitor in the synchronization method.
 *         Otherwise, an IllegalMonitorStateException will occur
 *      3.wait(),notify(),notifyAll()The three methods are defined in the java.lang.Object class.
 *
 * @author subei
 * @create 2020-05-08 18:50
 */

class Number implements Runnable{

    private int number = 1;
    public Object obj = new Object();

    @Override
    public void run() {

        while (true){
            synchronized (obj) {

                obj.notify();

                if(number <= 100){

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;

                    try {
                        //Make the thread calling the wait() method as follows enter the blocking state
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }else{
                    break;
                }
            }
        }
    }
}

public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);

        t1.setName("Thread 1");
        t2.setName("Thread 2");

        t1.start();
        t2.start();
    }
}

Similarities and differences between sleep() and wait()

 /**
 *Interview question: the similarities and differences between sleep() and wait()?
 *1. Same point: once the method is executed, the current thread can be blocked.
 *2. Differences: 1) the positions of the two method declarations are different: sleep() is declared in the Thread class, wait() is declared in the object class
 *2) different call requirements: sleep() can be called in any required scenario. wait() must be used in a sync block or sync method
 *3) about whether to release the synchronization monitor: if both methods are used in the synchronization code block or synchronization method, sleep() will not release the lock, and wait() will release the lock.
 *
 * @author shkstart
 *@ create 2019-02-15 4:21 PM
 */

Classic example: Producer / consumer issues

/**
 * Application of thread communication: classic example: Producer / consumer problem
 *
 * The producer gives the product to the clerk, and the customer takes the product from the clerk,
 * Shop assistants can only hold a fixed number of products (e.g. 20) at a time. If the producer tries to produce more products,
 * The clerk will ask the producer to stop. If there is a vacancy in the shop, he will inform the producer to continue production;
 * If there is no product in the store, the clerk will tell the consumer to wait,
 * If there is a product in the store, inform the consumer to take the product.
 *
 * analysis:
 *      1.Is it a multi-threaded problem? Yes, producer's thread, consumer's thread
 *      2.Is there a problem with sharing data? Yes, shop assistants, products, number of products
 *      3.How to solve the thread safety problem? There are three ways to synchronize
 *      4.Is thread communication involved? yes
 *
 * @author subei
 * @create 2020-05-08 19:23
 */

class Clerk{

    private int productCount = 0;

    //yield a product
    public synchronized void produceProduct() {

        if(productCount < 20){
            productCount++;
            System.out.println(Thread.currentThread().getName() + ": Start production" + productCount + "Products");

            notify();
        }else{
            //wait for
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    //Consumer products
    public synchronized void consumeProduct() {

        if(productCount > 0){
            System.out.println(Thread.currentThread().getName() + ":Start consuming" + productCount + "Products");
            productCount--;

            notify();
        }else{
            //wait for
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

class Producer extends Thread{//producer
    private Clerk clerk;

    public Producer(Clerk clerk){
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + ": Start production......");

        while(true){

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            clerk.produceProduct();
        }
    }
}

class Consumer extends Thread{  //consumer
    private Clerk clerk;

    public Consumer(Clerk clerk){
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println(getName() + ": Start consuming products......");

        while(true){

            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            clerk.consumeProduct();
        }

    }
}

public class ProductTest {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();

        Producer p1 = new Producer(clerk);
        p1.setName("Producer 1");

        Consumer c1 = new Consumer(clerk);
        c1.setName("Consumer 1");
        Consumer c2 = new Consumer(clerk);
        c2.setName("Consumer 2");

        p1.start();
        c1.start();
        c2.start();
    }
}				

New thread creation method of JDK 5.0

The third way to create multithreading: to implement the Callable interface

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

/**
 * The third way to create multithreading: to implement the Callable interface -- > Add JDK 5.0
 *
 * How to understand that the way to implement the Callable interface is more powerful than the way to implement the Runnable interface?
 *      1.call()Can have a return value.
 *      2.call()It can throw an exception, be caught by an external operation, and obtain the exception information
 *      3.Callable Is generic
 *      4.You need to use the FutureTask class, such as getting the return result
 *
 * @author subei
 * @create 2020-05-08 20:31
 */
//1. Create an implementation class to implement Callable
class NumThread implements Callable{

    //2. Implement the call method, and declare the operations that this thread needs to perform in the call()
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for(int i = 1;i <= 100;i++){
            if(i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}

public class ThreadNew {
    public static void main(String[] args) {
        //3. Create an object of the Callable interface implementation class
        NumThread numThread = new NumThread();

        //4. Pass the object of the Callable interface implementation class to the FutureTask constructor and create the FutureTask object
        FutureTask futureTask = new FutureTask(numThread);

        //5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread object, and call start()
        new Thread(futureTask).start();

        try {
            //6. Get the return value of the call method in the Callable
            //The get() return value is the return value of call() overridden by the FutureTask constructor parameter Callable implementation class.
            Object sum = futureTask.get();
            System.out.println("The sum is:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
  • Future interface
    • You can cancel the execution results of specific Runnable and Callable tasks, query whether they are completed, obtain results, etc.
    • FutrueTask is the only implementation class of Futrue interface
    • FutureTask also implements the Runnable, Future interface. It can be executed by the thread as Runnable, and can be used as Future to get the return value of Callable

Benefits of using thread pool

Background: resources that are often created and destroyed and used in a large amount, such as threads in concurrent situations, have a great impact on performance.

Idea: create many threads in advance, put them into the thread pool, get them directly when using them, and put them back into the pool after using them. It can avoid frequent creation, destruction and reuse. Similar to public transportation in life.

Benefits:

  • Faster response time (less time to create new threads)
  • Reduce resource consumption (reuse threads in thread pool, do not need to create every time)
  • Easy to manage threads
    • corePoolSize: the size of the core pool
    • maximumPoolSize: maximum number of threads
    • keepAliveTime: how long does the thread last at most when there is no task
    • ...

How to create multithreading: using thread pool

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

/**
 * How to create multithreading: using thread pool
 *
 * Benefits:
 *      1.Faster response time (less time to create new threads)
 *      2.Reduce resource consumption (reuse threads in thread pool, do not need to create every time)
 *      3.Easy to manage threads
 *          corePoolSize: Size of the core pool
 *          maximumPoolSize: Maximum threads
 *          keepAliveTime: How long does the thread last at most when there is no task
 *
 * Interview question: how many ways to create multithreading? Four!
 *
 * @author subei
 * @create 2020-05-08 21:05
 */

class NumberThread implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i <= 100;i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

class NumberThread1 implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i <= 100;i++){
            if(i % 2 != 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadPool {
    public static void main(String[] args) {

        //1. Provide thread pool with specified number of threads
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        //Set properties of thread pool
//        System.out.println(service.getClass());
//        service1.setCorePoolSize(15);
//        service1.setKeepAliveTime();

        //2. Execute the operation of the specified thread. You need to provide an object that implements the Runnable interface or the Callable interface implementation class
        service.execute(new NumberThread());  //Suitable for running
        service.execute(new NumberThread1());  //Suitable for running

//        service.submit(Callable callable); / / suitable for Callable

        //3. Close the connection pool
        service.shutdown();
    }
}
  • Thread pool related API

    • JDK 5.0 provides thread pool related API s: ExecutorService and Executors
  • ExecutorService: the real thread pool interface. Common subclass ThreadPoolExecutor

    • void execute(Runnable command): execute task / command without return value. It is generally used to execute Runnable
    • Future submit(Callable task): to execute a task, if there is a return value, it is usually called again
    • void shutdown(): close connection pool
  • Executors: tool class, factory class of thread pool, used to create and return different types of thread pools

    • Executors.newCachedThreadPool(): create a thread pool that can create new threads as needed
    • Executors.newFixedThreadPool(n); create a thread pool that can reuse a fixed number of threads
    • Executors.newSingleThreadExecutor(): create a thread pool with only one thread
    • Executors.newScheduledThreadPool(n): creates a thread pool that can be scheduled to run commands or execute periodically after a given delay.

    The whole Java stack series is my own notes. Writing is not easy. If you can, please give me a compliment! A kind of

66 original articles praised 261 visits 50000+
follow private letter

Tags: Windows Java JDK less

Posted on Sun, 17 May 2020 21:30:25 -0400 by ycoleman