java - 在另一个 Runnable 实现类中传递 Runnable 实例,其中前者的 run() 方法需要后者的引用
问题描述
我有一个类“ResourceConsumerThread”,它扩展了 Thread 并定义了一些行为。此类的多个实例(即多个线程)将具有不同的行为。我试图在创建 ResourceConsumerThread 类的实例时通过功能接口(Runnable)传递这些行为。ResourceConsumerThread 的 run() 方法只是调用 lambda 的方法 - run()。但是,我的要求是我传递的 lambda 需要引用它传递到的 ResourceConsumerThread 对象。
public class ResourceConsumingThread extends Thread {
//threads which have acquired resources that this thread is asking for.
private List<ResourceConsumingThread> dependencyList;
private List<Resource> acquiredResources;
private List<Resource> requestedResources;
private volatile boolean isDeadlockDetected;
private final String id;
private static int threadIdGenerator;
private final Runnable runnableBody;
private ResourceConsumingThread( Runnable runnableBody) {
this.dependencyList = new ArrayList<>();
this.acquiredResources = new ArrayList<>();
this.requestedResources = new ArrayList<>();
this.id = "T" + threadIdGenerator++;
this.runnableBody = runnableBody;
}
@Override
public void run() {
System.out.println("Running body for thread : " + id);
if(runnableBody != null){
runnableBody.run();
}else{
System.out.println("ERROR...threadBody can't be null.");
}
}
}
此类的用户将使用它,如下所示:
public void callerMethod(){
ResourceConsumingThread t1 = lockManager.createNewThread(new Runnable() {
@Override
public void run() {
lockManager.acquireLockOnResourceForThread(new Resource(), t1);
}
});
}
但是,由于 t1 尚未构建,我无法在 run() 方法中使用它 - 我收到编译器错误。
知道如何实现这一点,即使它涉及一些设计返工?主要要求是:
- LockManager.acquireLockOnResourceForThread() 需要知道哪个 ResourceConsumingThread 实例正在请求哪个 Resource。
- ResourceConsumingThread 的 run() 方法应该能够在不同的线程中执行不同的逻辑。
更新了我正在尝试的答案(不确定它是否正确的做法)。仍在等待通过社区获得潜在解决方案的更多天使。
final Map<String, Resource> resourceMap = new HashMap<>();
resourceMap.put("R1", new Resource());
final ResourceConsumingThread t1 = new ResourceConsumingThread();
Runnable t1Runnable = new Runnable() {
@Override
public void run() {
lockManager.acquireLockOnResourceForThread(resourceMap.get("R1"), t1);
}
};
t1.setRunnableBody(t1Runnable);
t1.start();
t1.join();
更新(在@Cliff 的评论之后):
ResourceConsumingThread t = lockManager.createNewThread(() -> {
lockManager.acquireLockOnResourceForThread(new Resource(), (ResourceConsumingThread) Thread.currentThread());
});
解决方案
我建议创建一个在其 run 方法中接受 ResourceConsumingThread 的功能接口。
interface ResourceRunnable {
void run(ResourceConsumingThread resourceThread);
}
这意味着将 ResourceConsumingThread 的构造函数更改为接受 ResourceRunnable。然后你可以这样做:
public void callerMethod(){
ResourceConsumingThread t1 = lockManager.createNewThread(new Runnable() {
@Override
public void run(ResourceConsumingThread resourceThread) {
lockManager.acquireLockOnResourceForThread(new Resource(), resourceThread);
}
});
}
ResourceConsumingThread 将在内部调用 ResourceRunnable.run(this) 。
更新: 正如我通过评论建议的那样,另一种方法是:
ResourceConsumingThread t = lockManager.createNewThread(() -> {
lockManager.acquireLockOnResourceForThread(new Resource(), (ResourceConsumingThread) Thread.currentThread());
});
推荐阅读
- python - 哪个 SKLearn 接口定义了 .fit、.predict 等
- c# - Selenium 无法在日期时间文本框中发送密钥
- visual-studio - Visual Studio 2019 内存分析器工具将托管堆中的所有对象列为 UNKNOWN
- c# - 在创建之前强制搜索
- testing - 对于新的测试用例,如何阻止 Tester 字段自动默认为创建卡片的人的名字?
- c - 用于表示图形的高效数据结构
- java - Travis CI 构建因 JUnit 5 失败
- python - Django 渲染() - 未找到“”的反向。'' 不是有效的视图函数或模式名称
- python - 用 sudo 安装 python 包有什么不明智的?
- azure - 如何使用 Azure REST Api 更新 Web 应用连接字符串