The basic use of the thread pool + Callable

The role of the thread pool

    1, to reduce the overhead of thread creation and switching

  • When not using the thread pool, to a task, you create a thread, we know that the system creates significant overhead and destruction of threads, and frequently create a thread means that require frequent thread switching, this is have a very large overhead.

    2, control the number of threads

  • Use a thread pool that we can effectively control the number of threads, when a large number of concurrent threads exist in the system, the system performance will lead to a sharp drop.

    3, limited recycling thread

  • Thread pool will advance to create some idle thread, they continue to work out tasks from the queue, and then execute, will continue to work with the next task in the queue after the execution, reducing the number of creation and destruction of threads, each thread It could have been reused, saving the overhead of creation and destruction.

Use the thread pool

    The thread pool are essentially used by the Java ThreadPoolExecutor or ForkJoinPool generated, except that different arguments passed to the corresponding thread pool is instantiated only by the constructor.

(. 1) the Executors is a thread pool class factory, the factory class set comprises the static factory method to create a thread pool:

  • newFixedThreadPool (): create a task a fixed size, task queue without limits, reusable, have a fixed number of threads in the thread pool (oom)
  • newSingleThreadExecutor (): create only one thread thread pool
  • newCachedThreadPool (): create a tool has a cache function of the thread pool
  • newScheduledThreadPool (): create a thread pool with the specified number of threads that can execute the task thread after a specified delay
  • newWorkStealingPool (): Creating hold enough threads in a thread pool to support a given level of parallel thread pool

(2) ExecutorService Interface Java thread pool is also used ideas oriented programming interface, you can see ThreadPoolExecutor and ForkJoinPool all implementation classes are ExecutorService interface defines some commonly used methods in ExecutorService interface, and then all kinds of threads in the pool ExecutorService can use methods defined by the interface, we have the following conventional methods:

Submit to the thread pool thread

  • The Submit Future () <?> : A Runnable object to the specified thread pool, thread pool to execute Runnable object that represents the thread when there is idle task, which receives both Runnable object can also receive a Callable object, which means the Sumbit () method may return a value.
  • void execute (Runnable command): only receive Runnable objects, it means that the method does not return a value.

Close the thread pool

  • void shutdown (): to prevent new task submission, will not have any impact on already submitted the task. (Wait for all the threads finished it off)
  • List <Runnable> shutdownNow (): to prevent new task submission, and it will interrupt thread currently running, while it will also workQueue tasks to remove, and add to the list of these tasks were returned. (Immediately shut down)

Check the thread pool status

  • boolean isShutdown (): After calling shutdown () or shutdownNow () method returns true
  • boolean isTerminated (): When you call shutdown () method, and return to true after the submission of all tasks completed; return true after the call when shutdownNow () method successfully stopped.

Common thread pool using the example

(1) newFixedThreadPool    (the number of threads in the pool is fixed, no matter how many tasks come)

package 线程池;

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

/**
 * @author Heian
 * @time 19/03/17 21:11
 * @copyright(C) 2019 深圳市北辰德科技股份有限公司
 * 用途:
 */
public class ExecutorSer {

    public static void sleepOneSecond(){
        try {
            TimeUnit.SECONDS.sleep (1);
        } catch (InterruptedException e) {
            e.printStackTrace ();
        }
    }
    public static void sleepFiveSecond(){
        try {
            TimeUnit.SECONDS.sleep (5);
        } catch (InterruptedException e) {
            e.printStackTrace ();
        }
    }
    public static void main(String[] args) {
        //(1)newFixedThreadPool(线程池中的线程数目是固定的,不管来了多少的任务)
        ExecutorService executorService = Executors.newFixedThreadPool (5);
        System.out.println ("FixedThreadPool" + executorService);
        //[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
        for (int i=0;i<6;i++) //定义6个任务
            executorService.execute (() -> {
                ExecutorSer.sleepOneSecond ();
                System.out.println (Thread.currentThread ().getName ());
            });
        System.out.println ("线程正在执行任务的状态:" +executorService);
        //[Running, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0] 如果是三个任务,则pool size=3 说明线程池是懒加载方式创建线程
        executorService.shutdown ();//此方法会让所有线程执行完毕后在关闭,shutdownNow:立马关闭
        System.out.println ("是否执行shutdown方法:"+ executorService.isShutdown () + "执行shutdown方法后状态:"+ executorService) ;
        //true ,[Shutting down, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0]
        System.out.println ("是否所有线程已经执行完毕:" + executorService.isTerminated ());

        ExecutorSer.sleepFiveSecond ();
        System.out.println ("5s后,是否执行shutdown方法:"+ executorService.isShutdown () + "执行shutdown方法后状态:"+ executorService) ;
        //true  执行shutdown方法后状态:java.util.concurrent.ThreadPoolExecutor@28864e92[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 6]
        System.out.println ("5s后,是否所有线程已经执行完毕:" + executorService.isTerminated ());//true
    }


}

(2) newSingleThreadExecutor (from start to finish the whole thread pool is only one thread at work)


 ExecutorService executorService1 = Executors.newSingleThreadExecutor ();
        for (int i=0;i<5;i++)
            executorService1.execute (() -> {
                System.out.println (Thread.currentThread ().getName ());
            });       
//可以看到至始至终就只有一个线程在执行任务
/*      pool-2-thread-1
        pool-2-thread-1
        pool-2-thread-1
        pool-2-thread-1
        pool-2-thread-1*/

(3)newCachedThreadPool


   ExecutorService executorService2 = Executors.newCachedThreadPool ();
        System.out.println (executorService2);
        for (int i=0;i<12;i++)
            executorService2.execute (() -> {
                ExecutorSer.sleepOneSecond ();
                System.out.println (executorService2);
            });
   System.out.println ("CacheThreadPool线程提交后,线程状态为" + executorService2);
  /*    java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
        CacheThreadPool线程提交后,线程状态为java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 12, queued tasks = 0, completed tasks = 0]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 12, queued tasks = 0, completed tasks = 0]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 12, queued tasks = 0, completed tasks = 0]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 12, queued tasks = 0, completed tasks = 0]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 12, queued tasks = 0, completed tasks = 0]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 8, queued tasks = 0, completed tasks = 4]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 7, queued tasks = 0, completed tasks = 5]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 6, queued tasks = 0, completed tasks = 6]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 5, queued tasks = 0, completed tasks = 7]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 5, queued tasks = 0, completed tasks = 7]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 3, queued tasks = 0, completed tasks = 9]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 2, queued tasks = 0, completed tasks = 10]
        java.util.concurrent.ThreadPoolExecutor@2096442d[Running, pool size = 12, active threads = 1, queued tasks = 0, completed tasks = 11]*/

(. 4) newScheduledThreadPool ( may be periodically or after a specified delay execution of threads in the thread pool of tasks )

//建立四个线程  每个500毫秒去打印当前线程的名称
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool (4);
        scheduledExecutorService.scheduleAtFixedRate (() -> {
            System.out.println (Thread.currentThread ().getName ());
        },0,500,TimeUnit.MILLISECONDS);

 

Use callable interface

     Callable interface is actually belong to functional classes Executor framework, similar functions Callable interface Runnable interface, but provides more powerful than Runnable function.

  • Callable can provide a return value at the end of the task, Runnable can not provide this function
  • Callable points of call method can throw an exception, but Runnable run method can not throw an exception.
package 线程池.ICallabl;

import java.util.concurrent.*;

/**
 * @author Heian
 * @time 19/03/23 22:27
 * 用途:模拟异步发送接口
 */
public class Icallable {


    //Callable泛型为其异步返回的结果类型  Callable函数式接口
    static class sendEmail implements Callable<String> {
        private long sleepTime;
        public sendEmail(long sleepTime) {
            this.sleepTime = sleepTime;
        }
        @Override
        public String call() throws Exception {
            Thread.sleep (sleepTime);
            System.out.println ("发送emails完毕:"+ Thread.currentThread ().getName ());
            return Thread.currentThread ().getName ();
        }
    }

    static class sendPhoneMsg implements Callable<String> {
        private long sleepTime;
        public sendPhoneMsg(long sleepTime) {
            this.sleepTime = sleepTime;
        }
        @Override
        public String call() throws Exception {
            Thread.sleep (sleepTime);
            System.out.println ("发送短信完毕:"+ Thread.currentThread ().getName ());
            return Thread.currentThread ().getName ();
        }
    }


    public static void main(String[] args) throws Exception{
        long start = System.currentTimeMillis ();
        sendEmail sendEmail = new sendEmail (5000);
        sendPhoneMsg sendPhoneMsg = new sendPhoneMsg (8000);

        FutureTask<String> sendEmailTask = new FutureTask<> (sendEmail);
        FutureTask<String> sendPhonneMsgTask = new FutureTask<> (sendPhoneMsg);

        ExecutorService executorService = Executors.newFixedThreadPool (3);//线程池中的线程数目是固定的,来了多少任务,启动多少线程
        executorService.execute (sendEmailTask);
        executorService.execute (sendPhonneMsgTask);
        while(true){
            if(!sendEmailTask.isDone ()){
                TimeUnit.MILLISECONDS.sleep (500);
                System.out.println ("enlias发送中,请稍后" + Thread.currentThread ().getName ());
            }
            if(!sendPhonneMsgTask.isDone ()){
                TimeUnit.MILLISECONDS.sleep (500);
                System.out.println ("短信发送中,请稍后"+ Thread.currentThread ().getName ());
            }
            if (sendEmailTask.isDone () && sendPhonneMsgTask.isDone ()){
                System.out.println ("两个线程执行完毕");
                executorService.shutdown ();//所有线程执行完毕后再关闭
                return;
            }
            //执行完成
            long end = System.currentTimeMillis ();
            System.out.println ("耗时" +(end-start) + "毫秒");
        }




    /*    while (true){// email:2  短信:5
            if (sendEmailTask.isDone ()){//isDone方法表示任务是否已经完成,若任务完成,则返回true;
                System.out.println ("email执行完毕" + sendEmailTask.get ());//方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
            }
            if (sendEmailTask.isDone () && sendPhonneMsgTask.isDone ()){
                System.out.println ("两个线程执行完毕");  
                executorService.shutdown ();//所有线程执行完毕后再关闭
                return;
            }
        }*/



    }


}

 

 

 

Guess you like

Origin blog.csdn.net/qq_40826106/article/details/88628536