- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对 ReentrantLock tryLock(timeout,timeUnit) 方法有一些困惑,当
运行下面的代码似乎 tryLock 超时,直到上一个线程结束,有人能解释一下吗?
public class MyService2 {
public ReentrantLock lock = new ReentrantLock();
public void waitMethod() {
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + " enter ");
boolean b = lock.tryLock(2, TimeUnit.SECONDS);
if (b) {
System.out.println(System.currentTimeMillis() + " lock begin:" + Thread.currentThread().getName());
for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
Math.random();
}
System.out.println(System.currentTimeMillis() + " lock end " + Thread.currentThread().getName());
return;
}
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + " got no lock end ");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
MyService2 myService2 = new MyService2();
Runnable runnable = myService2::waitMethod;
Thread thread1 = new Thread(runnable);
thread1.setName("T1");
thread1.start();
TimeUnit.MILLISECONDS.sleep(10);
Thread thread2 = new Thread(runnable);
thread2.setName("T2");
thread2.start();
}
运行这段代码后,结果是这样的
1555343172612 T1 enter
1555343172613 lock begin:T1
1555343172627 T2 enter
1555343179665 lock end T1
1555343179665 T2 got no lock end
我的问题是为什么线程 T2 不会在 2 秒内超时而不是等到线程 T1 结束?
但我刚刚发现:
例如,如果将 Math.random() 替换为 TimeUnit.SECONDS.sleep(1),则效果很好。
如果在 Debug模式下运行,它也可以正常工作。
最佳答案
这是一个有一些修改的替代方案:
首先,清理。更清晰的名字。更少的侵入性日志记录。相对时间值。
其次,两个计算线程启动之间的 0.1 秒 sleep 被移至每个线程中。这更清楚地赋予启动计算线程的线程优先权。
第三,启动线程与计算线程连接。即将计算的结论与启动线程联系起来。在原始代码中,计算线程启动后没有对其进行管理。如果计算线程打算不受管理,则需要记录下来。
第四,复制整个启动线程加上两个计算线程结构。即给予结构一个更真实的运行时环境,并将结构的不同行为一起呈现在一个 View 中。
修改的一个主题是使程序的预期行为和实际行为(通过日志输出查看)变得清晰。我们的目标是为这些内容提供最大程度的清晰度。
建议进行额外的修改,即将日志语句放入缓存中,然后在所有计算单元完成后显示收集的日志行。这消除了由日志语句引起的行为变化,这些变化通常是相当大的。
package my.tests;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private static long initialTime;
protected static void setInitialTime() {
initialTime = System.currentTimeMillis();
}
public static long getInitialTime() {
return initialTime;
}
public static final int CELL_COUNT = 10;
public static void main(String[] args) {
setInitialTime();
System.out.println("Beginning [ " + Integer.toString(CELL_COUNT) + " ] computation cells");
Thread[] cellThreads = new Thread[CELL_COUNT];
for ( int cellNo = 0; cellNo < CELL_COUNT; cellNo++ ) {
final String cellNoText = Integer.toString(cellNo);
Runnable computeCell = () -> {
(new LockTest(cellNoText) ).compute();
};
Thread cellThread = new Thread(computeCell);
cellThreads[cellNo] = cellThread;
}
// Start them all up ...
for ( Thread cellThread : cellThreads ) {
cellThread.start();
}
// Then wait for them all to finish ...
for ( Thread cellThread : cellThreads ) {
try {
cellThread.join();
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
}
}
System.out.println("Completed [ " + Integer.toString(CELL_COUNT) + " ] computation cells");
}
//
public LockTest(String cellName) {
this.cellName = cellName;
}
private final String cellName;
public String getCellName() {
return cellName;
}
// Logging ...
public String formatTime(long timeMs) {
return String.format("%12d (ms)", new Long(timeMs));
}
public long getRelativeTime(long currentTime) {
return currentTime - getInitialTime();
}
public String formatRelativeTime(long timeMs) {
return String.format(
"%12d %8d (ms)",
new Long(timeMs),
new Long( timeMs - getInitialTime() ));
}
public void log(String methodName, String message) {
long timeMs = System.currentTimeMillis();
String threadName = Thread.currentThread().getName();
System.out.println(
formatRelativeTime(timeMs) + ": " +
methodName + ": " +
threadName + ": " + message);
}
//
public void compute() {
log("compute", "ENTER: " + getCellName());
Runnable computation = () -> {
guardedComputation(
100L, 0, // Pause 0.1s before attempting the computation
1, TimeUnit.SECONDS, // Try to obtain the computation lock for up to 1.0s.
Integer.MAX_VALUE / 60 ); // Run this many computations; takes about 2s; adjust as needed
};
Thread computer1 = new Thread(computation);
computer1.setName( getCellName() + "." + "T1");
Thread computer2 = new Thread(computation);
computer2.setName( getCellName() + "." + "T2");
// Run two sets of computations:
//
// Each will pause for 0.1s before performing the computations.
//
// Performing computations requires a computation lock; wait up to 2.0s
// to acquire the lock.
computer1.start();
computer2.start();
try {
computer1.join();
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
try {
computer2.join();
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
log("compute", "RETURN: " + getCellName());
}
// Computation locking ...
private final ReentrantLock computationLock = new ReentrantLock();
public boolean acquireComputationLock(long maxWait, TimeUnit maxWaitUnit) throws InterruptedException {
return computationLock.tryLock(maxWait, maxWaitUnit);
}
public void releaseComputationLock() {
if ( computationLock.isHeldByCurrentThread() ) {
computationLock.unlock();
}
}
//
public void guardedComputation(
long pauseMs, int pauseNs,
long maxWait, TimeUnit maxWaitUnit, int computations) {
String methodName = "guardedComputation";
log(methodName, "ENTER");
try {
Thread.sleep(pauseMs, pauseNs);
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
try {
boolean didLock;
try {
didLock = acquireComputationLock(maxWait, maxWaitUnit);
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
String computationsText = Integer.toString(computations);
if ( didLock ) {
log(methodName, "Starting computations: " + computationsText);
for ( int computationNo = 0; computationNo < computations; computationNo++ ) {
Math.random();
}
log(methodName, "Completed computations: " + computationsText);
} else {
log(methodName, "Skipping computations: " + computationsText);
}
} finally {
releaseComputationLock();
}
log(methodName, "RETURN");
}
}
关于java - ReentrantLock tryLock(timeout,timeUnit) 无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55692957/
我正在使用ExecutorService.invokeAll(Callable, timeout, TimeUnit)方法 在提交给 ExecutorService 的每个 Callable 中,我都
我注意到 TimeUnit 类的一个奇怪行为,所以我创建了这个最小的示例来重现它。 long differenceInDays; Calendar c1 = Calendar.getInstance(
我正在尝试制作一个基本的倒数计时器。老实说,我通过教程了解了其中的大部分内容,所以我并不完全理解它的工作原理,但我已经尝试了几个小时来寻找答案,但我不知道还能去哪里寻找。 我在 TimeUnit 之后
我正在尝试研究一些方法和对能够每周使用一次的操作/“命令”的响应(防止垃圾邮件)。我唯一的问题是如何将我的java时间设置为一周。这就是我所拥有的: public static long displa
一 点睛 sleep 是一个静态方法,它有两个重载方法,其中一个需要传入毫秒数,另外一个需要传入毫秒数和纳秒数。 sleep 的方法 public static native void sleep(l
JavaAPI:https://docs.oracle.com/javase/8/docs/api/index.html 1 TimeUnit api:https://docs.oracle.com/
JavaAPI:https://docs.oracle.com/javase/8/docs/api/index.html 1 TimeUnit api:https://docs.oracle.com/
我正在使用 Python selenium 3.0.1 版,其中似乎没有说 driver.implicitly_wait(10) 我们现在必须说 driver.implicitly_wait(10,
是否有可能像 TimeUnit 这样的枚举作为参数传递给方法?我正在编写一个 Java 方法,该方法需要 long 作为持续时间参数,并且很好奇是否有更好的方法来做到这一点。基本上,我想将一些东西传递
如何为用户传递 TimeUnit 的类创建 API,例如分钟、秒、小时和一个数字,并在类内部保留毫秒值。 以下似乎是唯一的方法? void someMethodDays(int numOfDays)
我创建了这样的方法,其中有 2 个输入。 first is type (e.g. 'd', 'h') second is value (e.g. "15", "0.5") 我创建了将它转换为分钟的函数
我想将 TimeUnit 转换为 seconds 或 hours ,我问了很多但没有得到满意的答案。我读过http://developer.android.com/reference/java/uti
我正在尝试实现 Future.get(long, TimeUnit)在 TimeUnit.timedWait(Object, long) 方面. 目前尚不清楚如何使用 TimeUnit.timedWa
我试图计算两个时间戳的天数之差,TimeUnit 为我返回了完全错误的结果。 这是我的代码: long ts = 1522242239952L; long now = 1527274162820L;
我只是想知道,为什么 Java 的 TimeUnit 类中缺少一些枚举? 实际上最大时间单位是 DAY,而我想使用 WEEK、YEAR... 最佳答案 TimeUnit.DAYS 常量表示 24 小时
我希望将任意值从毫秒转换为秒,我的首选是 TimeUnit.MILLISECONDS.toSeconds。但是它返回一个长整数,因此将 1 毫秒转换为 0 秒而不是 0.001 秒。 阅读时the d
#include #include #include using namespace std; class TimeUnit { public: TimeUnit(int m, int
如何使用 Simple XML 库(版本 2.6.5/2.6.6)序列化 java.util.concurrent.TimeUnit? 这是我想要序列化的类: @Root(name="settings
我正在使用 java.util.concurrent.TimeUnit 类,我发现了一些有趣的约定,我不知道,我不明白是关于枚举的,我已经举了一个例子我自己的,我希望有人能向我解释.. 一个带有方法的
我正在尝试计算两天之间的天数差。由于某种原因,比较 01-03-2013 和 01-04-2013 给出结果 30,比较 01-03-2013 和 31-03-2013 也是如此 Calendar c
我是一名优秀的程序员,十分优秀!