Java Advanced Application - Multithreading - (3) Implement the Callable interface and use the thread pool to create threads

Implement the Callable interface
• Compared with using Runnable, Callable is more powerful
– Compared with the run() method, it can have a return value
– The method can throw an exception
Support generic return values ​​(you need to use the FutureTask class to get the return result)

• Future interface (understanding)
– can cancel the execution results of specific Runnable and Callable tasks, query whether they are completed
, obtain results, etc.
– FutureTask is the only implementation class of Future interface
– FutureTask implements Runnable and Future interfaces at the same time. It can be executed by threads as Runnable, and can also be used as Future to get the return value of Callable
• Disadvantage: When obtaining the execution results of sub-threads, the current thread (or main thread) is blocked, which is inefficient.
Code example:

/*
* 创建多线程的方式三:实现 Callable (jdk5.0 新增的)
*/
//1.创建一个实现 Callable 的实现类
class NumThread implements Callable {
    
    
 //2.实现 call 方法,将此线程需要执行的操作声明在 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 CallableTest {
    
    
 public static void main(String[] args) {
    
    
 //3.创建 Callable 接口实现类的对象
 NumThread numThread = new NumThread();
 //4.将此 Callable 接口实现类的对象作为传递到 FutureTask 构造器中,创建 FutureTask 的对象
 FutureTask futureTask = new FutureTask(numThread);
 //5.将 FutureTask 的对象作为参数传递到 Thread 类的构造器中,创建 Thread 对象,并调用 start()
 new Thread(futureTask).start();
// 接收返回值
 try {
    
    
 //6.获取 Callable 中 call 方法的返回值
 //get()返回值即为 FutureTask 构造器参数 Callable 实现类重写的 call()的返回值。
 Object sum = futureTask.get();
 System.out.println("总和为:" + sum);
 } catch (InterruptedException e) {
    
    
 e.printStackTrace();
 } catch (ExecutionException e) {
    
    
 e.printStackTrace();
 }
 }
}

Using the thread pool
Existing problem:
If there are a lot of concurrent threads, and each thread ends after executing a short task, frequent creation of threads will greatly reduce the efficiency of the system, because frequent creation and destruction of threads needs time.

So is there a way to make threads reusable, that is, after executing a task, it is not destroyed, but can continue to execute other tasks?

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

insert image description here

Benefits:
• Improve response speed (reduce the time to create new threads)
• Reduce resource consumption (reuse threads in the thread pool, do not need to create each time)
• Facilitate thread management
– ​​corePoolSize: core pool size
– maximumPoolSize: maximum thread Number
– keepAliveTime: When the thread has no tasks, how long will it keep at most before it will be terminated
– …
thread pool related API
• Before JDK5.0, we had to manually customize the thread pool. Starting from JDK5.0, Java has built-in API related to thread pool
. Thread pool related APIs are provided under the java.util.concurrent package: ExecutorService and
Executors.
• ExecutorService: The real thread pool interface. Common subclass ThreadPoolExecutor
– void execute(Runnable command): Execute tasks/commands, without return value,
generally used to execute Runnable
– Future submit(Callable task): Execute tasks, have return
value, generally execute Callable
– void shutdown( ) : Close the connection pool
• Executors: A thread pool factory class, through which static factory methods can create various types of thread
pool objects.
– Executors.newCachedThreadPool(): Creates a thread that can create new threads as needed
Executors.newFixedThreadPool
(int nThreads); Create a reusable
thread pool with a fixed number of threads – Executors.newSingleThreadExecutor(): Create a thread pool
with only one thread – Executors.newScheduledThreadPool(int corePoolSize): Create a thread A pool that can schedule commands to run after a given delay or periodically. Code example:



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);
 }
 }
 }
}
class NumberThread2 implements Callable {
    
    
 @Override
 public Object call() throws Exception {
    
    
 int evenSum = 0;//记录偶数的和
 for(int i = 0;i <= 100;i++){
    
    
 if(i % 2 == 0){
    
    
 evenSum += i;
 }
 }
 return evenSum;
 }
}
public class ThreadPoolTest {
    
    
 public static void main(String[] args) {
    
    
 //1. 提供指定线程数量的线程池
 ExecutorService service = Executors.newFixedThreadPool(10);
 ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
// //设置线程池的属性
// System.out.println(service.getClass());//ThreadPoolExecutor
 service1.setMaximumPoolSize(50); //设置线程池中线程数的上限
 //2.执行指定的线程的操作。需要提供实现 Runnable 接口或 Callable 接口实现类的对象
 service.execute(new NumberThread());//适合适用于 Runnable
 service.execute(new NumberThread1());//适合适用于 Runnable
 try {
    
    
 Future future = service.submit(new NumberThread2());//适合使用于 Callable
 System.out.println("总和为:" + future.get());
 } catch (Exception e) {
    
    
 e.printStackTrace();
 }
 //3.关闭连接池
 service.shutdown();
 }
}

Guess you like

Origin blog.csdn.net/weixin_45817985/article/details/130950096