乐趣区

关于java:线程池的使用

例如:

    private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, Runtime.getRuntime().availableProcessors() * 2,
            0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ptyadapter-qd-%d").build());

这段代码次要是定义了一个线程池 EXECUTOR_SERVICE 以及创立该线程池的一些参数和属性。

线程池是一种常见的治理线程的技术,它可能无效的控制线程的数量、复用线程、治理线程的生命周期和优化线程的性能等等。在该代码中,指定了线程池的总容量为 CPU 核数的两倍,应用的队列类型为 LinkedBlockingQueue,它是一个基于链表实现的无界阻塞队列,能够存储任意数量的元素。队列中的工作会期待线程池中闲暇的线程去执行,如果没有闲暇线程则会始终阻塞,期待有闲暇线程后再去执行。

该线程池中的线程都被标记为守护线程(daemon=true),即当主线程完结时,这些子线程也会随之完结。线程的名称采纳了相似于 ptyadapter-qd-1 这样的命名形式,数字局部是线程池内的线程计数器值。

具体参数的含意如下:

corePoolSize:线程池中保留的最小线程数。
maximumPoolSize:线程池中容许存在的最大线程数。
keepAliveTime:线程池中超过 corePoolSize 线程数目的闲暇线程在终止之前期待新工作的最长工夫。
unit:keepAliveTime 工夫单位。
workQueue:用于贮存期待执行工作的队列,其中可寄存有限个元素。
threadFactory:线程池中创立新线程的线程工厂。
这段代码的作用是在初始化时创立一个线程池,用于并发解决一些耗时的工作,并且该线程池具备较好的性能和容错机制。咱们能够通过调用 EXECUTOR_SERVICE.submit() 办法来提交一个工作到该线程池中,该线程池会依据理论状况来调度和执行这个工作。这种做法能够无效地进步程序的并发性能,并且不会像间接创立线程一样造成过多的线程资源节约。


  while (true) {list.forEach((key, value) ->{Future<?> future = EXECUTOR_SERVICE.submit(() -> {if ("2".equals(value)) {return;}
                    if ("1".equals(value)) {return;}
                    // 结构 http 申请
                    BufferedReader reader = null;
                    VoucherRetionVo efmVouBillRelation = new VoucherRetionVo();
                    efmVouBillRelation.setIpConfig(key);
                    efmVouBillRelation.setMaxNum(size.get());
                    try {ObjectMapper objectMapper = new ObjectMapper();
                        objectMapper.writeValueAsString(efmVouBillRelation);
                        String url = "http://" + key + "/pty/online/gz";
                        URL requestUrl = new URL(url);
                        HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection();
                        connection.setRequestMethod("POST");
                        connection.setRequestProperty("Content-Type", "application/json");
                        connection.setDoOutput(true);
                        connection.getOutputStream().write(objectMapper.writeValueAsString(efmVouBillRelation).getBytes());
                        reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                    } catch (Exception e) {LOG.error("拜访谬误请查看", e);
                    } finally {if (null != reader) {
                            try {reader.close();
                            } catch (IOException e) {e.printStackTrace();
                            }
                        }
                    }
                    if (size.get() == 0) {LOG.info("工作实现,上班");
                        return;
                    }
                    size.getAndDecrement();});
                taskList.add(future);
            });
            for (Future<?> future : taskList) {future.get(120, TimeUnit.SECONDS);
            }
            // 达到要求完结循环
            if (size.get() == 0) {LOG.info("工作实现,上班");
                break;
            }
        }

这段代码蕴含一个有限循环,其中蕴含了线程池的调用,用于并发解决一些工作。

首先遍历 list 中的每个键值对,key 是字符串类型的 IP 地址,value 值类型为字符串,其值别离为 “1” 或 “2”。如果 value 值等于 “2”,示意该服务须要重启,间接跳过;如果 value 值等于 “1”,示意该服务正在生成原始单据,也间接跳过。其余状况下,将依据 key 和 size 参数结构一个 HTTP 申请,并将该申请提交到线程池中,以便异步地并发解决这些申请。

具体步骤如下:

创立一个 VoucherRetionVo 对象,并设置相干属性值。
依据 key 结构 HTTP 申请的 URL。
创立一个 URL 对象和一个 HttpURLConnection 对象,设置相干属性值和申请头信息。
向 HTTP 申请中写入申请体(即 VoucherRetionVo 对象序列化后的 JSON 字符串)。
发送 HTTP 申请,并读取响应后果。
敞开相干的 IO 流资源。
如果 size 值为 0,示意工作曾经全副实现,退出循环。
注意事项:

通过调用 Future.get() 办法阻塞线程,期待该线程执行结束并返回后果。
须要在 try-catch-finally 中开释 IO 资源。
整个循环在每次执行之前须要期待上一次执行完结,即先期待以后线程池中的所有工作执行完结,而后再持续下一次循环,直到工作全副实现。


Future.get() 办法用于阻塞以后线程并期待异步工作执行实现并返回后果。当线程池中的某个工作执行实现后,能够通过调用 Future.get() 办法获取该工作的执行后果。如果在指定工夫内(在这段代码中为 120 秒)工作未能执行结束,则会抛出 TimeoutException 异样。

如果你须要获取异步工作的执行后果,那么就须要应用 Future.get() 办法并在其中进行解决。在本段代码中,并没有对异步工作的返回值进行解决,而是只是期待工作执行结束,因而不须要应用该办法来获取异步工作的返回值。如果你须要获取异步工作的执行后果,请批改代码,在 submit 办法返回的 Future 对象上调用 get 办法以获取异步工作的返回值,并对其进行相应的解决。


Future 的作用:
应用 Future 对象能够实现异步计算(即线程池中的工作)的后果获取。通常状况下,咱们须要期待某个或某些异步工作执行结束能力进行下一步操作(例如获取异步工作的返回值并依据其后果进行相应的解决),这时候就能够应用 Future。

具体地说,将异步工作提交到线程池后,线程池会返回一个 Future 对象,这个对象能够用来查问工作以后的执行状态,或期待工作执行实现并返回执行后果。在期待工作执行实现时,能够应用 Future.get() 办法阻塞以后线程,直到异步工作执行实现并返回异步工作的执行后果。

此外,Future 还能够用于治理多个并发的异步工作。例如,能够通过 Future 对象来实现异步工作的超时机制、勾销异步工作的执行等。另外一些高级性能,例如,把多个 Future 组合成一个 Future,使它们执行结束后再执行某些操作,也能够应用 Future 来实现。

因而,应用 Future 能够简化异步工作的治理和管制,进步程序的并发性和效率。

退出移动版