线程如何使用(线程实现的三种方法)
导语:线程策略之我们该怎么合理使用
我们都知道线程的4种丢弃策略,但是有时候会为了选择哪种策略犯了难,
下面我按照自己的理解给大家白话一下:
4种线程丢弃策略:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
1.应用场景1
线程可以忽略,例如做一些宽泛统计,例如登录人数等
这个时候我们可以选择DiscardPolicy或者DiscardOldestPolicy
2.应用场景2
线程必须执行,否则抛出异常,这个时候我们可以选择AbortPolicy,
这种场景说实话比较少,一般我们想执行,肯定是要执行完的,而不是终止线程
3.应用场景3
线程必须执行,如果线程数和队列都满的情况下,我们交给主线程执行
这种情况的坏处是,很容易cpu飚的过高,或者直接内存溢出
重点来了,现实情况下我们执行多线程任务是希望我们的任务
像流水一样执行,不是太慢,也不是太快,例如我们执行读取文件,
多线程处理然后入库,我们都知道读取文件的速度是非常快的,而处理
入库是非常慢:
代码如下:
File file=new File(&34;);
FileInputStream fis = new FileInputStream(file);
BufferedReader br=new BufferedReader(new InputStreamReader(fis));
while ((line = br.readLine()) != null) {
//threadPoolExecutor自定义线程池,我们的抛弃策略选择的是CallerRunsPolicy
//SyncDataCallable我们实现了Callable接口的线程
threadPoolExecutor.submit(new SyncDataCallable(line));
}
我们知道while其实是非常快,如果我们的代码真的这样跑的话,
环境基本上直接就瘫痪了,这个时候怎么办呢?
其实我们可以通过读取线程的执行状态来判断存活的线程,
如果线程在一定数量之外,我们可以让主线程sleep一下,等待子线程执行完,
然后再继续往我们的线程池里面扔任务
示例如下:
List<Future<String>> futureList=new Vector<>();
while ((line = br.readLine()) != null) {
//当线程数量超过10的时候,这里面执行清空futureList
if (futureList.size() > 10) {
removeFuture(futureList);
}
Future<String> future = threadPoolExecutor.submit(new SyncDataCallable(line));
futureList.add(future);
}
//移除isDone完成的线程
public void removeFuture(List<Future<String>> futureList) throws InterruptedException {
if(null!=futureList){
Thread.sleep(200L);
List<Future<String>> removeFutures=new Vector<>();
futureList.forEach(future -> {
if(future.isDone()) {
removeFutures.add(future);
}
});
removeFutures.forEach(future -> {
futureList.remove(future);
});
}
}
小伙伴们,你们get到了吗?
欢迎指正,或者有更好的方法提出来!
本文内容由小里整理编辑!