例如:
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());
上述Java代码定义了一个名为EXECUTOR_SERVICE的静态变量,它是一个线程池对象。这个线程池对象使用了ThreadPoolExecutor类来创建,并且包含以下几个参数:
1、corePoolSize和maximumPoolSize参数都是Runtime.getRuntime().availableProcessors() * 2,表示核心线程数和最大线程数都是当前系统可用的CPU核心数的两倍。
2、keepAliveTime参数表示当线程池中的线程数大于核心线程数时,多余的空闲线程在等待新任务到来时最多保持的时间。这里设置为0毫秒,表示多余的线程会立即停止。
3、unit参数表示keepAliveTime参数的单位,这里设置为毫秒。
4、workQueue参数表示线程池中的任务队列,这里使用了LinkedBlockingQueue类来创建一个无限制大小的队列,即可以不限数量的向队列中添加任务。
5、threadFactory参数表示创建线程的工厂类,这里使用了ThreadFactoryBuilder类来创建线程,同时设置线程名称前缀为ptyadapter-qd-,并把线程标记为守护线程(daemon),以便程序退出时自动结束线程。
他会根据资源自己控制资源
这个线程池对象可以用来执行异步任务,其内部维护一定数量的线程,根据队列中的任务自动调度线程来执行任务。这样可以有效地利用系统资源,并提高程序的性能和响应速度。
线程池是一种常见的管理线程的技术,它能够有效的控制线程的数量、复用线程、管理线程的生命周期和优化线程的性能等等。在该代码中,指定了线程池的总容量为 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 可以简化异步任务的管理和控制,提高程序的并发性和效率。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。