长久以来网上博客,或微信公众号都有些多线程或者并发处理的工具的文章,类型分为两种:
第一类:
介绍各类j.u.c包下的工具,并解释源码的
第二类:
浅尝止咳介绍一些多线程或并发相关的工具
这两类都没有问题,但是都存在一个问题,少有对jdk新增工具和少见或少用的工具做完整汇总及介绍,大部分千篇一律都是那几个熟悉的工具看多了之后难免让人不再想看下去,本片博文我就来整理一下少见到的工具,少见只是相对而言没有绝对。
未完结整理中…
/**
* <h2>可重入读写锁<h2>
* 应用场景:
* <p>对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,
* 所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写
* 的操作了。
* 特点:
* <p>此锁的读,写锁是可以相互转换的,其他读写锁只能让写锁降级成读锁,却不能读锁升级为写锁。
* 在读的的时候允许多个线程同时读取
* @since 1.5
* @author Doug Lea
*
*/
ReentrantReadWriteLock
/**
* <h2>CompletionService<h2>
* 应用场景:
* <p>每个线程执行完都又返回结果,但是每个线程执行时长不一样,需要无阻塞获取每一个线程执行完成后的结果
* 特点:
* <p>减少阻塞只要有线程返回结果就能马上获取
* @since 1.8
*/
CompletionService
/**
* 为了更好的说明应用场景需要一个demo示例
*/
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
*
* @author kk
*
*/
public class Demo {
static int count = 0;
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newCachedThreadPool();
CompletionService<String> completionService = new ExecutorCompletionService<>(executor);
for (int i = 0; i < 10; i++) {
completionService.submit(new Task(i));
}
executor.shutdown();
// 阻塞方式
for (int i = 0; i < 10; i++) {
// 检索并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。
Future<String> future = completionService.take(); // 这一行没有完成的任务就阻塞
System.out.println("--2.3--> " + future.get()); // 这一行在这里不会阻塞,引入放入队列中的都是已经完成的任务
}
System.out.println("--2.4--> main Thread end:");
// 无阻塞方式
while(completionService.poll() != null) {
Future<String> future = completionService.take(); // 这一行没有完成的任务就阻塞
System.out.println("--2.3--> " + future.get()); // 这一行在这里不会阻塞,引入放入队列中的都是已经完成的任务
}
}
}
class Task implements Callable<String> {
private volatile int i;
public Task(int i) {
this.i = i;
}
@Override
public String call() throws Exception {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
return "--0.1--> 任务 : " + i;
}
}
/**
* <h2>CompletableFuture<h2>
* 应用场景:
* <p>需要流水线式的处理方式使用它无疑是最贴切的一个场景,下一步总是依赖总是依赖上一步的操作最终在合并全部数据进行操作
* 特点:
* <p>在使用上,语义更加清晰明确代,码更加简练,支持链式调用,更专注业务逻辑,方便的处理异常情况
* @since 1.8
* @author Doug Lea
*/
CompletableFuture
/**
* 为了更好的说明应用场景需要一个demo示例
*/
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
*
* @author kk
*
*/
public class CompletableFutureDemo {
@SuppressWarnings("static-access")
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
// 任务 1:查詢數據庫获取数据
CompletableFuture<String> queryTask =
CompletableFuture.supplyAsync(() -> {
System.out.println("queryTask 开始工作: 查詢數據庫...");
sleepSeconds(5);//睡眠五秒
return "查詢數據庫";
}).supplyAsync(()->{
System.out.println(" 數據處理計算...");
sleepSeconds(3);
return "數據處理計算";
});
// 任务 2:调用遠程接口获取数据
CompletableFuture<String> apiTask =
CompletableFuture.supplyAsync(() -> {
System.out.println("apiTask 开始工作: 调用遠程接口获取数据...");
sleepSeconds(3);
return "接口數據";
});
// 任务 3:任务 1 和任务 2 完成后执行,聚合结果
CompletableFuture<String> polymerizationTask =
queryTask .thenCombine(apiTask , (t1Result, t2Result) -> {
System.out.println("polymerizationTask开始工作" + t1Result + " 与 " + t2Result + "实现計算逻辑处理");
return "處理後聚合结果";
});
// 等待任务 3 执行结果
String result = polymerizationTask.get(6, TimeUnit.SECONDS);
System.out.println("主线程获取polymerizationTask的结果:" + result);
System.out.println("执行任务需要的毫秒值: " + (System.currentTimeMillis() - startTime) + "毫秒");
}
// 睡眠工具类
static void sleepSeconds(int timeout) {
try {
TimeUnit.SECONDS.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}