我在syncCmd
函数中有同步块:
public Object Sync = new Object();
public void syncCmd(String controlCmd) {
synchronized(Sync) {
...
}
}
如果一个线程占用Sync
并完成其工作,我需要添加一些逻辑。在这种情况下,我想向系统报告"too busy"
而不是排队。了解某人是否已占用Sync
部分的最佳方式是什么?如何知道本节中有多少线程在等待?一切都在Java 1.4.
答案 0 :(得分:2)
查看Lock
界面及其实现ReentrantLock
。它允许您使用tryLock()
方法,包括允许在资源已被锁定时等待一段时间的变体:
private ReentrantLock lock = new ReentrantLock();
public void syncCmd(String controlCmd) {
if (lock.tryLock()) {
try {
// Use your synchronized resource here
} finally {
lock.unlock();
}
} else {
// Failed to lock
}
}
遗憾的是,Java 1.4没有java.util.concurrency
包,我认为你最好的选择是通过synchronized
和双重检查来实现相同的逻辑:
public class Lock {
private final Object lock = new Object();
private volatile boolean locked = false;
public boolean tryLock() {
if (!locked) {
synchronized (lock) {
if (!locked) {
locked = true;
return true;
}
}
}
return false;
}
public void unlock() {
synchronized (lock) {
locked = false;
}
}
}
它不会像使用现代JVM中处理器指令支持的CAS循环的ReentrantLock
一样快,但它可以完成这项工作。
此实现也不可重入,您可以扩展它以跟踪锁定线程并在需要重入时锁定计数。
重要更新: @Stephen C非常清楚Java 1.4中的double check is broken,并始终牢记这一点。但是有例外。例如,短基元类型。所以,我认为它将适用于这种特殊情况。有关详细信息,请查看"Double-Checked Locking is Broken" Declaration。
答案 1 :(得分:1)
同步块/方法和原始互斥体在Java中无法做到这一点。
但是如果您使用Lock
代替javadoc),则可以使用tryLock
从不阻止或仅在有限时间内阻止。
示例:
Lock l = new ReentrantLock();
if (l.tryLock()) {
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
else {
// report "too busy"
}
但请注意,使用"尝试......最后"和一个明确的unlock()
调用,以确保始终释放锁。 (与synchronized
构造不同,它会自动为您处理。)
在Java 1.5之前,没有我在纯Java中知道的解决方案。这可能是本机代码欺骗,但我不知道如何。
您/您的管理层应该寻求在您的产品中放弃对Java 1.4的支持,以及从依赖于它的任何第三方产品迁移。许多年前,Java 1.5本身就是EOL。实际上,Java 1.8之前的所有版本都已经过EOL& d;请参阅Oracle Java SE Support Roadmap文档。
答案 2 :(得分:1)
上面的两个答案谈到java.util.concurrent.locks.ReentrantLock
,但它在Java 1.4中不存在。
太糟糕了,难过?
没有!如果系统库和第三方库没有按您的要求提供,请自行编写!
以下代码可以满足您的要求,而且完全没有。我个人不会在没有首先添加一些可以使它更有用,更可测试,更重要的是更加万无一失的功能的情况下使用它。
我只是提供给你作为开始的地方的一个例子。
public class ExtremelySimplisticNonReentrantLock {
boolean isLocked = false;
/**
* @return true if the lock was acquired, false otherwise.
*/
public synchronized boolean tryToAcquire() {
if (isLocked) {
return false;
}
isLocked = true;
return true;
}
public synchronized void release() {
lsLocked = false;
}
}
分享并享受!
答案 3 :(得分:0)
试试这个(两个类 - Executor和Tracker):
执行人:
package com.example.so.jdk1_4.synch;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* <p> For http://stackoverflow.com/questions/38671520/not-wait-in-case-synchronized-section-is-occupied </p>
* @author Ravindra HV
*/
public class InUseExample {
public synchronized void execute(String command) {
InUseTracker.obtainClassInstance().setInuse(true);
try {
System.out.println("Executing :"+command);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}// do work
InUseTracker.obtainClassInstance().setInuse(false);
}
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("Start :"+new Date());
testInUseExample();
System.out.println("Final wait count :"+InUseTracker.obtainClassInstance().waitCount());
System.out.println("End :"+new Date());
}
private static void testInUseExample() {
final InUseExample inUseExample = new InUseExample();
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
InUseTracker.obtainClassInstance().incrementWaitCount();
while(true) {
if( InUseTracker.obtainClassInstance().isInuse() == false ) { // reduces the chances of this thread going to a block mode..
inUseExample.execute(Thread.currentThread().getName());
break;
}
else {
try {
Random random = new Random();
String message = Thread.currentThread().getName()+" - block in use by :"+InUseTracker.obtainClassInstance().getInUseBy();
message = message+" "+". Wait Count :"+InUseTracker.obtainClassInstance().waitCount();
System.out.println(message);
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
InUseTracker.obtainClassInstance().decrementWaitCount();
}
}
};
int threadCount = 10;
List<Thread> threadPoolTemp = new ArrayList<Thread>();
for(int i=0;i<threadCount;i++) {
Thread thread = new Thread(runnable);
threadPoolTemp.add(thread);
}
for (Thread thread : threadPoolTemp) {
thread.start();
}
for (Thread thread : threadPoolTemp) {
try {
thread.join(); // wait until all threads have executed..
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
追踪器:
package com.example.so.jdk1_4.synch;
/**
* <p> For http://stackoverflow.com/questions/38671520/not-wait-in-case-synchronized-section-is-occupied </p>
* @author Ravindra HV
*/
public class InUseTracker {
private boolean inuse;
private int waitCount;
private String inUseBy;
private static InUseTracker DEFAULT_INSTANCE = new InUseTracker();
private InUseTracker() {
}
public static InUseTracker obtainClassInstance() {
return DEFAULT_INSTANCE;
}
public synchronized boolean isInuse() {
return inuse;
}
public synchronized void setInuse(boolean inuse) {
this.inuse = inuse;
if(inuse) {
setInUseBy(Thread.currentThread().getName());
}
else {
setInUseBy("");
}
}
private void setInUseBy(String inUseBy) {
this.inUseBy = inUseBy;
}
public synchronized String getInUseBy() {
return inUseBy;
}
public synchronized void incrementWaitCount() {
waitCount++;
}
public synchronized void decrementWaitCount() {
waitCount--;
}
public synchronized int waitCount() {
return waitCount;
}
}
PS:猜猜你必须移动
InUseTracker.obtainClassInstance().setInuse(false);
在最终的if或酌情。