java.util.stream.Stream#filter 是一个强大的方法,允许开发者对数据流进行筛选。然而,从方法名本身有歧义,这让我们无法直观地知道哪些数据会被保留:是true被过滤掉,还是保留?
这就需要我们去看API文档,如果能自己写demo,然后Run一下,就会记忆得更清楚。
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
/**
* @Auther: cheng.tang
* @Date: 2024/6/23
* @Description: tool-box
*/
public class Java8StreamFilterTest {
@Test
public void streamFilterTest() {
List<Integer> result = Stream.of(1, 2, 3).filter(i -> i > 1).collect(Collectors.toList());
assertThat(result).isEqualTo(Arrays.asList(2, 3));
}
}
在没Run之前,你能确定是pass还是fail呢?
剖析:这个java.util.stream.Stream#filter()有歧义,到底是满足什么条件才能留下呢?
改进建议:
使用java.util.stream.Stream#filterIfTrue来替代java.util.stream.Stream#filter
java.util.Collections#sort 方法用于对集合进行排序,但方法名本身并没有明确指出是升序还是降序。这可能导致开发者在使用时产生疑惑,尤其是当集合元素的自然排序不是预期的顺序时。
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
/**
* @Auther: cheng.tang
* @Date: 2024/6/23
* @Description: tool-box
*/
public class JavaCompareToTest {
@Test
public void compareToTest() {
List<Integer> dataList = Arrays.asList(1, 20, 30, 100);
Collections.sort(dataList, (o1, o2) -> o2.compareTo(o1));
assertThat(dataList).isEqualTo(Arrays.asList(100, 30, 20, 1));
}
}
在没有运行前,你能通过上面的代码,确定是passed还是fail呢?
Run:
当然一旦掌握了这种技能,填了坑,就会越来越“资深”。
不过,Java8中已经fix: dataList.sort(Comparator.reverseOrder());//降序 dataList.sort(Comparator.naturalOrder());//升序
@Test
public void compareToJava8Test() {
List<Integer> dataList = Arrays.asList(1, 20, 30, 100);
dataList.sort(Comparator.reverseOrder());
assertThat(dataList).isEqualTo(Arrays.asList(100, 30, 20, 1));
dataList.sort(Comparator.naturalOrder());
assertThat(dataList).isEqualTo(Arrays.asList(1, 20, 30, 100));
}
Run:
java.util.concurrent.ThreadPoolExecutor#shutdownNow
方法用于立即关闭线程池,并尝试停止所有正在执行的任务。然而,方法名并没有直接告诉我们它还会返回一个包含未执行任务的列表。
package com.tangcheng.toolbox.business.api;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadPoolApiTest {
@Test
public void testShutdownNow() throws InterruptedException {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100),
new ThreadPoolExecutor.DiscardOldestPolicy());
int totalThreadCount = 10;
CountDownLatch exitController = new CountDownLatch(totalThreadCount);
for (int i = 1; i <= totalThreadCount; i++) {
// 产生一个任务,并将其加入到线程池
String task = "task@ " + i;
log.info("put {} ", task);
threadPool.execute(new Runnable() {
@Override
public void run() {
log.info(" begin task {} ", task);
try {
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException ignored) {
log.warn(" InterruptedException {} ", task);
}
log.info(" end task {} ", task);
exitController.countDown();
}
});
}
log.info("before invoke threadPool.shutdownNow() threadPool.getTaskCount() {} threadPool.getActiveCount() {} threadPool.getPoolSize() {} ", threadPool.getTaskCount(), threadPool.getActiveCount(), threadPool.getPoolSize());
List<Runnable> tasksShutdownNowReturn = threadPool.shutdownNow();
log.info("after invoke threadPool.shutdownNow() threadPool.getTaskCount() {} tasksShutdownNowReturn.size {} threadPool.getActiveCount() {} threadPool.getPoolSize() {} ", threadPool.getTaskCount(), tasksShutdownNowReturn.size(), threadPool.getActiveCount(), threadPool.getPoolSize());
boolean awaitResult = exitController.await(3, TimeUnit.MINUTES);
log.info("after await tthreadPool.getTaskCount() {} tasksShutdownNowReturn.size {} threadPool.getActiveCount() {} threadPool.getPoolSize() {} ", threadPool.getTaskCount(), tasksShutdownNowReturn.size(), threadPool.getActiveCount(), threadPool.getPoolSize());
log.info(" awaitResult {} ", awaitResult);
}
}
执行结果:
09:41:25.259 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 1
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 2
09:41:25.265 [pool-1-thread-1] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - begin task task@ 1
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 3
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 4
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 5
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 6
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 7
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 8
09:41:25.265 [pool-1-thread-2] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - begin task task@ 2
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 9
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - put task@ 10
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - before invoke threadPool.shutdownNow() threadPool.getTaskCount() 10 threadPool.getActiveCount() 2 threadPool.getPoolSize() 2
09:41:25.265 [pool-1-thread-2] WARN com.tangcheng.toolbox.business.api.ThreadPoolApiTest - InterruptedException task@ 2
09:41:25.265 [pool-1-thread-1] WARN com.tangcheng.toolbox.business.api.ThreadPoolApiTest - InterruptedException task@ 1
09:41:25.266 [pool-1-thread-2] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - end task task@ 2
09:41:25.266 [pool-1-thread-1] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - end task task@ 1
09:41:25.265 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - after invoke threadPool.shutdownNow() threadPool.getTaskCount() 2 tasksShutdownNowReturn.size 8 threadPool.getActiveCount() 2 threadPool.getPoolSize() 2
09:44:25.270 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - after await tthreadPool.getTaskCount() 2 tasksShutdownNowReturn.size 8 threadPool.getActiveCount() 0 threadPool.getPoolSize() 0
09:44:25.271 [main] INFO com.tangcheng.toolbox.business.api.ThreadPoolApiTest - awaitResult false
可以看到:在执行 shutdownNow() 方法之后,首先会给所有线程池中的线程发送 interrupt 中断信号,尝试中断这些任务的执行,然后会将任务队列中正在等待的所有任务转移到一个 List 中并返回。
改进建议:
在调用此方法时,添加注释或使用更明确的命名,以避免混淆。
ThreadPoolExecutor#shutdownAndInterruptRunningThTaskNowAndRemoveAllWaitingTaskAndReturn()来替代ThreadPoolExecutor#shutdownNow
方法名是不是有点长了?是的,但命名不怕长,就怕一看就糊涂。
良好的方法命名是代码可读性的关键。一个见名知意的方法名可以让其他开发者快速理解其功能和行为。此外,遵循单一职责原则,确保一个方法只做一件事,也是提高代码清晰度的有效手段。通过这些实践,我们可以减少误解,提高代码的可维护性和可读性。
“ 任何傻瓜都会编写计算机能理解的代码。 好的程序员能够编写人能够理解的代码。 ” 好代码的要求: 1、有意义的命名。 “见名知意”,代码要在字面上表达其含义,字面编程 2、单一职责。 每个函数、类、模块都专注于做一件事, 且这些函数、类、方法、实体等尽可能少 唐成,公众号:的数字化之路如果代码有段位,来看看你是什么段位?青铜?白银?还是黄金?【有源码】
线程池了解吗?说说线程池中 shutdown和shutdownNow的区别?
长开了呀
不知道从6月初的那一天开始,看到楼梯不想爬了,也不知道是因为走廊黑还是因为阶梯高