我需要为很多用户安排定期工作.此作业将以固定速率运行,间隔时间.我希望在该时间间隔内统一分配每个用户的作业执行.例如,如果间隔是4天,我将使用一致的散列函数和每个用户的标识符来同时安排作业,例如.每隔4天,第3天.
间隔是相对于所有用户都相同的原始时刻.给定这样的原点瞬间,像Instant#EPOCH或其他一些常数值,如何找到当前间隔的开始日期?
我可以
Instant now = Instant.now();
Instant origin = Instant.EPOCH;
Duration interval = Duration.ofDays(4);
Duration duration = Duration.between(origin, now);
long sinceOrigin = duration.toMillis();
long millisPerInterval = interval.toMillis();
long intervalsSince = sinceOrigin / millisPerInterval;
Instant startNext = origin.plus(interval.multipliedBy(intervalsSince));
int cursor = distributionStrategy.distribute(hashCode, millisPerInterval);
Run Code Online (Sandbox Code Playgroud)
然后我可以使用它cursor来调度Instant相对于当前间隔开始的作业.
这里有很多数学,我不确定在任何地方转换到毫秒都会维持实际日期.是否有更精确的方法来划分两个时刻之间的时间并找到我们目前所处的那一个(细分)?
当G1决定它需要开始进行混合收集时,它会将我们的伊甸园空间从10g大幅缩小到大约1g.
{Heap before GC invocations=294 (full 0):
garbage-first heap total 20480000K, used 18304860K [0x00000002de000000, 0x00000002de804e20, 0x00000007c0000000)
region size 8192K, 1363 young (11165696K), 11 survivors (90112K)
Metaspace used 37327K, capacity 37826K, committed 38096K, reserved 1083392K
class space used 3935K, capacity 4081K, committed 4096K, reserved 1048576K
2016-03-31T20:57:31.002+0000: 7196.427: [GC pause (G1 Evacuation Pause) (young)
Desired survivor size 717225984 bytes, new threshold 1 (max 1)
- age 1: 41346816 bytes, 41346816 total
7196.427: [G1Ergonomics (CSet Construction) start choosing CSet, _pending_cards: 144693, predicted base …Run Code Online (Sandbox Code Playgroud) 根据文件,XX:InitiatingHeapOccupancyPercent
设置触发标记周期的Java堆占用阈值.默认占用率是整个Java堆的45%.
在我目前的环境中,这种情况不会发生.
我的G1垃圾收集配置如下
-Xms25000m
-Xmx25000m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=1000
-XX:GCTimeRatio=99
-XX:InitiatingHeapOccupancyPercent=70
-XX:MaxTenuringThreshold=8
-XX:+UnlockExperimentalVMOptions
-XX:G1MixedGCCountTarget=16
-XX:G1OldCSetRegionThresholdPercent=3
-XX:G1NewSizePercent=30
-XX:G1RSetUpdatingPauseTimePercent=5
Run Code Online (Sandbox Code Playgroud)
使用25g堆和XX:InitiatingHeapOccupancyPercent70%堆时,您会期望在18g被占用时开始标记周期.我正在拖尾垃圾收集日志,但这不会发生.
这是一个摘录:
{Heap before GC invocations=592 (full 0):
garbage-first heap total 25600000K, used 22802164K [0x00000001a5800000, 0x00000001a60061a8, 0x00000007c0000000)
region size 8192K, 1526 young (12500992K), 25 survivors (204800K)
Metaspace used 37386K, capacity 37948K, committed 38144K, reserved 1083392K
class space used 3948K, capacity 4080K, committed 4096K, reserved 1048576K
2016-04-20T22:06:38.272+0000: 4213.406: [GC pause (GCLocker Initiated GC) (young)
Desired survivor size 801112064 bytes, new …Run Code Online (Sandbox Code Playgroud) 我在主机上运行Cassandra 2.2.11(并且不会升级).我在cron作业中定期运行nodetool命令进行监控.nodetool实现为另一个使用JMX与Cassandra java进程通信的java进程.我每分钟发出五个左右的命令.
偶尔(不是任何可识别的模式),执行nodetool将失败NoClassDefFoundError,引用类来自java.lang.例如,
java.lang.NoClassDefFoundError: java/lang/Thread (wrong name: java/lang/Thread)
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
at java.lang.Class.getDeclaredField(Class.java:2068)
at java.util.concurrent.FutureTask.<clinit>(FutureTask.java:476)
at java.util.concurrent.ScheduledThreadPoolExecutor.scheduleWithFixedDelay(ScheduledThreadPoolExecutor.java:590)
at sun.rmi.transport.tcp.TCPChannel.free(TCPChannel.java:347)
at sun.rmi.server.UnicastRef.free(UnicastRef.java:431)
at sun.rmi.server.UnicastRef.done(UnicastRef.java:448)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:132)
at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:205)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1955)
at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1922)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:287)
at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270)
at org.apache.cassandra.tools.NodeProbe.connect(NodeProbe.java:183)
at org.apache.cassandra.tools.NodeProbe.<init>(NodeProbe.java:150)
at org.apache.cassandra.tools.NodeTool$NodeToolCmd.connect(NodeTool.java:302)
at org.apache.cassandra.tools.NodeTool$NodeToolCmd.run(NodeTool.java:242)
at org.apache.cassandra.tools.NodeTool.main(NodeTool.java:158)
Run Code Online (Sandbox Code Playgroud)
在此堆栈跟踪中,错误发生在类初始化期间FutureTask.我也见过
java.lang.NoClassDefFoundError: java/lang/Object (wrong name: java/lang/Object)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethod(Class.java:2128)
at java.lang.invoke.MethodHandleImpl$Lazy.<clinit>(MethodHandleImpl.java:614) …Run Code Online (Sandbox Code Playgroud) 我有两个班级:
class Outer {
Inner inner = new Inner("value");
}
class Inner {
private final String value;
Inner(String value) {
this.value = value;
}
}
public Optional<Outer> getOptionalValue() {
return Optional.of(new Outer());
}
Run Code Online (Sandbox Code Playgroud)
我的测试:
public void testCLass() {
Assertions.assertThat(getOptionalValue())
.isPresent()
.map(v -> v.inner.value)
.isEqualTo("value");
}
Run Code Online (Sandbox Code Playgroud)
我希望它通过,因为isPresentunwraps 可选,map转换Outer为value最后一种方法,我只是比较字符串。
但它在最后一行失败并显示以下消息:
Expecting:
<Optional[value]>
to be equal to:
<"value">
but was not.
Run Code Online (Sandbox Code Playgroud)
我不知道为什么不展开可选
我有一个异步 API,它本质上是通过分页返回结果
public CompletableFuture<Response> getNext(int startFrom);
Run Code Online (Sandbox Code Playgroud)
每个Response对象都包含一个偏移量列表startFrom和一个标志,该标志指示是否还有更多剩余元素,因此是否getNext()需要发出另一个请求。
我想编写一个方法来遍历所有页面并检索所有偏移量。我可以像这样以同步方式编写它
int startFrom = 0;
List<Integer> offsets = new ArrayList<>();
for (;;) {
CompletableFuture<Response> future = getNext(startFrom);
Response response = future.get(); // an exception stops everything
if (response.getOffsets().isEmpty()) {
break; // we're done
}
offsets.addAll(response.getOffsets());
if (!response.hasMore()) {
break; // we're done
}
startFrom = getLast(response.getOffsets());
}
Run Code Online (Sandbox Code Playgroud)
换句话说,我们在0处调用getNext()with。startFrom如果抛出异常,我们就会短路整个过程。否则,如果没有偏移,我们就完成。如果有偏移,我们将它们添加到主列表中。如果没有更多的东西需要获取,我们就完成了。否则,我们将重置startFrom为我们获取的最后一个偏移量并重复。
理想情况下,我想在不阻塞CompletableFuture::get()并返回CompletableFuture<List<Integer>>包含所有偏移量的情况下执行此操作。
我怎样才能做到这一点?我如何编写期货来收集结果?
我正在考虑“递归”(实际上不是在执行中,而是在代码中)
private CompletableFuture<List<Integer>> recur(int startFrom, List<Integer> offsets) …Run Code Online (Sandbox Code Playgroud) 鉴于..
List<Foo> copy(List<Foo> foos) {
return foos
.stream()
.map(foo -> new Foo(foo))
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
IntelliJ IDEA 2016.1.1报告new Foo(foo)"可以用方法参考替换".
我知道Foo::newno-arg构造函数的语法,但是没有看到我如何foo作为参数传入.我肯定在这里遗漏了一些东西.
通常使用CompletableFuture,我会在结果可用时立即调用thenApply或其他方法来执行某些操作.但是,我现在有一种情况,我希望处理结果,直到我收到一个肯定的结果,然后忽略所有进一步的结果.
如果我只想获得第一个可用的结果,我可以使用CompletableFuture.anyOf(虽然我讨厌将列表转换为数组只是为了调用anyOf).但这不是我想要的.我想取第一个结果,如果它没有理想的结果,那么我想处理第二个可用结果,依此类推,直到得到理想的结果.
这是一个简单的例子,它遍历所有结果并返回它找到的大于9的第一个值.(注意,这不是我真正的任务.这只是一个简单的例子.)
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
for(CompletableFuture<Integer> result : results) {
Integer v = result.get();
if(v > 9)
return v;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
当然,这个例子从一开始就经历了结果,而不是在完成时查看结果.所以这里有一个可以实现我想要的东西,但代码要复杂得多.
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
AtomicInteger finalResult = new AtomicInteger();
CountDownLatch latch = new CountDownLatch(results.size());
for(CompletableFuture<Integer> result : results) {
result.whenComplete((v,e) -> {
if(e!=null) {
Logger.getLogger(getClass()).error("",e);
} else if(v > 9) {
finalResult.set(v);
while(latch.getCount() > 0)
latch.countDown();
return;
}
latch.countDown();
});
}
latch.await();
if(finalResult.get() > 9)
return finalResult.get();
return null;
}
Run Code Online (Sandbox Code Playgroud)
有没有api,我可以这样做?
public …Run Code Online (Sandbox Code Playgroud) 考虑请求 - 响应协议.
我们生成一个线程来执行一个select()循环,用于读取和写入已接受的非阻塞SocketChannel.这可能看起来像
while (!isStopped()) {
selector.select();
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey selectedKey = selectedKeys.next();
selectedKeys.remove();
Context context = (Context) selectedKey.attachment();
if (selectedKey.isReadable()) {
context.readRequest();
} else /* if (selectedKey.isWritable()) */ {
context.writeResponse();
}
}
}
Run Code Online (Sandbox Code Playgroud)
where Context只是一个容器,用于相应的SocketChannel,一个缓冲区和逻辑来读入它并从中写入.在readRequest可能看起来像
public void readRequest() {
// read all content
socketChannel.read(requestBuffer);
// not interested anymore
selectionKey.interestOps(0);
executorService.submit(() -> {
// handle request with request buffer and prepare response
responseBuffer.put(/* some response …Run Code Online (Sandbox Code Playgroud) 在阅读RTMP规范后,为了编写一个基本的RTMP服务器,我无法确定是否可以通过同一块流(块流ID)发送多个消息(消息流ID)。
第5.3.2节分享了两个示例:一个示例,其中具有相同流ID的多个消息通过多个块依次发送给单个块流ID,另一个示例是通过多个块按单个块流ID发送单个消息。
但是,没有示例说明针对单个块流ID在多个块上同时发送具有不同流ID的多条消息。我找不到能阻止这种情况的任何东西,但我想确认一下。
例如,假设您有两条消息,如示例2所示
+-----------+-------------------+-----------------+-----------------+
| | Message Stream ID | Message TYpe ID | Time | Length |
+-----------+-------------------+-----------------+-----------------+
| Msg # 1 | 27 | 9 (video) | 1000 | 307 |
+-----------+-------------------+-----------------+-----------------+
| Msg # 2 | 42 | 9 (video) | 1000 | 197 |
+-----------+-------------------+-----------------+-----------------+
Run Code Online (Sandbox Code Playgroud)
RTMP客户端可以发送以下块顺序吗?
换句话说,是否希望块3使用1或2中的标头(即基于消息流ID)?
java ×9
java-8 ×3
g1gc ×2
assertj ×1
asynchronous ×1
classloading ×1
concurrency ×1
heap-memory ×1
java-stream ×1
java-time ×1
jodatime ×1
nio ×1
optional ×1
reflection ×1
rtmp ×1
sockets ×1