Basic concepts and use of thread pools in Java programming

  • 2020-04-01 04:23:44
  • OfStack

Reason for introducing thread pools
Because thread life cycle includes creating, ready, running, blocked, destruction of stage, when dealing with a number of tasks to be is small, we can create several threads to handle the corresponding tasks, but when there are a large number of tasks, due to create, destroy, thread takes a lot of overhead, use the thread pool has greatly reduced these problems.

Use of thread pools
We only need to use Executors class to provide us with a static method, can create the corresponding thread pool:


  public static ExecutorSevice newSingleThreadExecutor()

  public static ExecutorSevice newFixedThreadPool()

  public static ExecutorSevice newCachedThreadPool()

When the newSingleThreadExecutor returns a single threaded Executor and hands over multiple tasks to the Exector, the thread processes one task and then the next, and if the thread fails, a new thread replaces it.

NewFixedThreadPool returns a thread pool with a specified number of threads, and if the number of tasks exceeds the number of threads, no unperformed tasks must wait until any are completed.

NewCachedThreadPool creates threads for processing based on the number of tasks the user has to perform. The thread pool does not limit the number of threads, and is completely dependent on the number of threads that the JVM can create, which can cause a lack of memory.

We just need to put the task to be executed into the run method and give the implementation class of the Runnable interface to the execute method of the thread pool as one of its parameters, as shown below:


Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable(){
  public void run(){
    //Tasks performed
 }
}

If you need to pass parameters to a task, you can do this by creating an implementation class for the Runnable interface.

Example 3.
(1) : newSingleThreadExecutor
MyThread. Java


publicclassMyThread extends Thread {
  @Override
  publicvoid run() {
    System.out.println(Thread.currentThread().getName() + " Be executing... ");
  }
}
TestSingleThreadExecutor.java
publicclassTestSingleThreadExecutor {
  publicstaticvoid main(String[] args) {
    //Create a pool of threads that can reuse a fixed number of threads
    ExecutorService pool = Executors. newSingleThreadExecutor();
    //The Runnable interface object is created, and the Thread object, of course, implements the Runnable interface
    Thread t1 = new MyThread();
    Thread t2 = new MyThread();
    Thread t3 = new MyThread();
    Thread t4 = new MyThread();
    Thread t5 = new MyThread();
    //Put the thread into the pool for execution
    pool.execute(t1);
    pool.execute(t2);
    pool.execute(t3);
    pool.execute(t4);
    pool.execute(t5);
    //Turn off the thread pool
    pool.shutdown();
  }
}

The output


pool-1-thread-1 Be executing... 
pool-1-thread-1 Be executing... 
pool-1-thread-1 Be executing... 
pool-1-thread-1 Be executing... 
pool-1-thread-1 Be executing... 

(2) : newFixedThreadPool
TestFixedThreadPool. Java


publicclass TestFixedThreadPool {
  publicstaticvoid main(String[] args) {
    //Create a pool of threads that can reuse a fixed number of threads
    ExecutorService pool = Executors.newFixedThreadPool(2);
    //The Runnable interface object is created, and the Thread object, of course, implements the Runnable interface
    Thread t1 = new MyThread();
    Thread t2 = new MyThread();
    Thread t3 = new MyThread();
    Thread t4 = new MyThread();
    Thread t5 = new MyThread();
    //Put the thread into the pool for execution
    pool.execute(t1);
    pool.execute(t2);
    pool.execute(t3);
    pool.execute(t4);
    pool.execute(t5);
    //Turn off the thread pool
    pool.shutdown();
  }
}

The output


pool-1-thread-1 Be executing... 
pool-1-thread-2 Be executing... 
pool-1-thread-1 Be executing... 
pool-1-thread-2 Be executing... 
pool-1-thread-1 Be executing... 

(3) : newCachedThreadPool
TestCachedThreadPool. Java


publicclass TestCachedThreadPool {
  publicstaticvoid main(String[] args) {
    //Create a pool of threads that can reuse a fixed number of threads
    ExecutorService pool = Executors.newCachedThreadPool();
    //The Runnable interface object is created, and the Thread object, of course, implements the Runnable interface
    Thread t1 = new MyThread();
    Thread t2 = new MyThread();
    Thread t3 = new MyThread();
    Thread t4 = new MyThread();
    Thread t5 = new MyThread();
    //Put the thread into the pool for execution
    pool.execute(t1);
    pool.execute(t2);
    pool.execute(t3);
    pool.execute(t4);
    pool.execute(t5);
    //Turn off the thread pool
    pool.shutdown();
  }
}

Output results:


pool-1-thread-2 Be executing... 
pool-1-thread-4 Be executing... 
pool-1-thread-3 Be executing... 
pool-1-thread-1 Be executing... 
pool-1-thread-5 Be executing... 

(4) : newScheduledThreadPool
TestScheduledThreadPoolExecutor. Java


publicclass TestScheduledThreadPoolExecutor {
  publicstaticvoid main(String[] args) {
    ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
    exec.scheduleAtFixedRate(new Runnable() {//Exceptions are fired every once in a while
           @Override
           publicvoid run() {
              //throw new RuntimeException();
              System.out.println("================");
           }
         }, 1000, 5000, TimeUnit.MILLISECONDS);
    exec.scheduleAtFixedRate(new Runnable() {//Every once in a while print the system time to prove that the two are independent
           @Override
           publicvoid run() {
              System.out.println(System.nanoTime());
           }
         }, 1000, 2000, TimeUnit.MILLISECONDS);
  }
}

The output


================
8384644549516
8386643829034
8388643830710
================
8390643851383
8392643879319
8400643939383


Related articles: