Java API文档声明combiner该collect方法的参数必须是:
用于组合两个值的关联,非干扰,无状态函数,它必须与累加器函数兼容
A combiner是BiConsumer<R,R>接收两个类型的参数R并返回void.但是文档没有说明我们是否应该将元素组合到第一个或第二个参数中?
例如,以下示例可以给出不同的结果,取决于组合的顺序是: m1.addAll(m2)或m2.addAll(m1).
List<String> res = LongStream
.rangeClosed(1, 1_000_000)
.parallel()
.mapToObj(n -> "" + n)
.collect(ArrayList::new, ArrayList::add,(m1, m2) -> m1.addAll(m2));
Run Code Online (Sandbox Code Playgroud)
我知道在这种情况下我们可以简单地使用方法句柄,例如ArrayList::addAll.然而,在某些情况下需要Lambda并且我们必须以正确的顺序组合项目,否则我们可能在并行处理时得到不一致的结果.
这是否在Java 8 API文档的任何部分中声明了?或者它真的没关系?
最近,我从" 多处理器编程的艺术 "第8章中读到了一些关于" 监视器和阻塞同步 "的例子,这些例子使用了signalAll()一个Condition对象,而没有获得与之相关的锁Condition.
令人惊讶的是,我没有在本书的勘误表中找到任何修复这些例子的方法.此外,他们建议对a的图8.12的例子进行修正FifoReadWriteLock,但他们继续使用signalAll()没有锁定的情况.这扰乱了我,我试图找到关于这些示例的其他注意事项,以了解这些Java示例以这种方式编写的原因.
例如,问题的答案 " 读写互斥锁如何工作?"显示了a的实现的相同示例FifoReadWriteLock,它实现了writeUnlock():
void writeUnlock() {
writer = false;
condition.signalAll();
}
Run Code Online (Sandbox Code Playgroud)
关于没有锁定获取,您可以阅读两个不同的原因:
由于本书使用了Java中的示例并明确说明了以下内容,因此很难接受第一个参数:
本书使用Java编程语言.
关于第二点,我知道方法的java.util.concurrent.locks.Condition状态中的Java API signal():
当调用此方法时,实现可能(并且通常确实)要求当前线程保持与此关联的锁
Condition.
如果仅" 实施可能 ",则意味着它不是强制性的.然而,据我所知,我发现任何不符合此要求的实施方案.所以我想知道哪些Java Condition实现不需要当前线程来保存锁?
parallel-processing multithreading locking java.util.concurrent concurrent-programming
在Async Http Client文档中,我看到如何获取Future<Response>异步HTTP Get请求的结果,例如:
AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient();
Future<Response> f = asyncHttpClient
.prepareGet("http://api.football-data.org/v1/soccerseasons/398")
.execute();
Response r = f.get();
Run Code Online (Sandbox Code Playgroud)
但是,为方便起见,我希望得到一个CompletableFuture<T>替代方案,我可以应用一个将结果转换为其他内容的延续,例如将响应内容从Json反序列化为Java对象(例如SoccerSeason.java).这就是我想做的事情:
AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient();
CompletableFuture<Response> f = asyncHttpClient
.prepareGet("http://api.football-data.org/v1/soccerseasons/398")
.execute();
f
.thenApply(r -> gson.fromJson(r.getResponseBody(), SoccerSeason.class))
.thenAccept(System.out::println);
Run Code Online (Sandbox Code Playgroud)
根据Async Http Client文档,执行此操作的唯一方法是通过AsyncCompletionHandler<T>对象和使用promise.所以我为此构建了一个辅助方法:
CompletableFuture<Response> getDataAsync(String path){
CompletableFuture<Response> promise = new CompletableFuture<>();
asyncHttpClient
.prepareGet(path)
.execute(new AsyncCompletionHandler<Response>() {
@Override
public Response onCompleted(Response response) throws Exception {
promise.complete(response);
return response;
}
@Override …Run Code Online (Sandbox Code Playgroud) 我正在将.Net Framework库迁移到.Net标准,并且编译器无法从中找到核心构建器System.Reflection.Emit.
如果我在正确的位置,那么API文档声明这些构建器(MethodBuilder,ModuleBuilder和AssemblyBuilder)是其中的一部分System.Reflection.Emit.
这是project.json我的图书馆:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable"
},
"dependencies": {},
"frameworks": {
"netstandard1.6": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我还需要其他参考吗?
为什么我们不能将委托的实例转换为泛型类型T?
考虑一个CreateDelegate创建T实例的实用程序方法,它是一个委托,即派生自的类型MulticastDelegate.
T CreateDelegate<T>() {… }
Run Code Online (Sandbox Code Playgroud)
不幸的是,泛型不允许约束T到从MulticastDelegate给出以下编译错误派生的类型:
约束不能是特殊类'System.MulticastDelegate'
然而,这种实用方法是检查T与MulticastDelegateReflection through 兼容并创建委托Delegate::CreateDelegate.但是,如果我们尝试将结果转换Delegate::CreateDelegate为T,我们将得到以下编译错误:
无法将类型'System.Delegate'转换为'T'
但是,如果我先将它转换为object然后T它会正常工作:
T h = (T) ((object) Delegate.CreateDelegate(typeof(T), target, m));
Run Code Online (Sandbox Code Playgroud)
为什么我们不能直接将代表委托给T?
关于如何跳过从Files.lines获得的偶数行的问题,我遵循接受的答案filterEven()方法,基于Spliterator<T>接口实现我自己的方法,例如:
public static <T> Stream<T> filterEven(Stream<T> src) {
Spliterator<T> iter = src.spliterator();
AbstractSpliterator<T> res = new AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED)
{
@Override
public boolean tryAdvance(Consumer<? super T> action) {
iter.tryAdvance(item -> {}); // discard
return iter.tryAdvance(action); // use
}
};
return StreamSupport.stream(res, false);
}
Run Code Online (Sandbox Code Playgroud)
我可以通过以下方式使用:
Stream<DomainObject> res = Files.lines(src)
filterEven(res)
.map(line -> toDomainObject(line))
Run Code Online (Sandbox Code Playgroud)
然而,测量这种方法对下一个使用filter()副作用的方法的性能时,我注意到下一个方法表现更好:
final int[] counter = {0};
final Predicate<String> isEvenLine = item -> ++counter[0] % 2 == 0;
Stream<DomainObject> res …Run Code Online (Sandbox Code Playgroud) Spliterator从Stream管道中获取 a可能会返回StreamSpliterators.WrappingSpliterator的实例。例如,得到以下内容Spliterator:
Spliterator<String> source = new Random()
.ints(11, 0, 7) // size, origin, bound
.filter(nr -> nr % 2 != 0)
.mapToObj(Integer::toString)
.spliterator();
Run Code Online (Sandbox Code Playgroud)
鉴于上述情况Spliterator<String> source,当我们通过 的tryAdvance (Consumer<? super P_OUT> consumer)方法(Spliterator在本例中为StreamSpliterators.WrappingSpliterator的实例)单独遍历元素时,它将首先将项目累积到内部缓冲区中,然后再消费这些项目,如我们在StreamSpliterators.java中所见#298。从简单的角度来看,doAdvance()首先将项目插入到buffer,然后获取下一个项目并将其传递给consumer.accept (…)。
public boolean tryAdvance(Consumer<? super P_OUT> consumer) {
boolean hasNext = doAdvance();
if (hasNext)
consumer.accept(buffer.get(nextToConsume));
return hasNext;
}
Run Code Online (Sandbox Code Playgroud)
但是,我没有弄清楚 this 的需要buffer。
在这种情况下,为什么不简单地将 的 …
一旦我安装了JDK 8,我就无法在Windows 7上再次将命令提示符设置为JDK 7.
我已经为两者设置了系统环境属性,JAVA_HOME并PATH指向JDK7和我的JDK7/bin文件夹,我也重新启动了SO,每次打开一个新的命令提示符并运行时,java -version我总是得到Java的第8版.
在Java环境设置中,我也启用了JDK 7.

如何再次为JDK 7配置命令提示符?
使用AsyncHttpClientwith Netty提供程序将阻止主程序在执行异步请求时终止.例如,下面的程序后终止println,或没有,这取决于供应商是否JDKAsyncHttpProvider还是NettyAsyncHttpProvider:
public class Program {
public static CompletableFuture<Response> getDataAsync(String uri) {
final AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
final CompletableFuture<Response> promise = new CompletableFuture<>();
asyncHttpClient
.prepareGet(uri)
.execute(new AsyncCompletionHandler<Response>(){
@Override
public Response onCompleted(Response resp) throws Exception {
promise.complete(resp);
asyncHttpClient.close(); // ??? Is this correct ????
return resp;
}
});
return promise;
}
public static void main(String [] args) throws Exception {
final String uri = "…";
System.out.println(getDataAsync(uri).get());
}
}
Run Code Online (Sandbox Code Playgroud)
关于AsynHttpClient文档说明: …
从简单的角度来看,lambda表达式被编译成static方法,因为它们不捕获this(即不访问实例成员).
public class App {
public static void foo(){
Consumer<Integer> c1 = n -> {};
Consumer<Integer> c2 = n -> {};
}
public static void main(String [] args) {
Supplier<String> sup1 = () -> "I am sup1";
Supplier<String> sup2 = () -> "I am sup2";
Supplier<String> sup3 = () -> "I am sup3";
Stream.of(App.class.getDeclaredMethods()).forEach(System.out::println);
}
}
Run Code Online (Sandbox Code Playgroud)
运行前面的例子,并检查与生成的字节码javap工具,我们可以看到,通过变量称为lambda表达式c1,c2,sup1,sup2,sup3被编译成与名称的方法:
lambda$foo$0lambda$foo$1lambda$main$2lambda$main$3lambda$main$4然而,如果我们打印出getClass() …