在另一个Runnable实现类中传递Runnable实例,其中run()方法的前者需要稍后引用

时间:2018-05-04 13:48:58

标签: java multithreading lambda

我有一个课程' ResourceConsumerThread'它扩展了Thread并定义了一些行为。此类的多个实例(即多个线程)将具有不同的行为。我正在尝试通过功能接口(Runnable)传递这些行为,同时创建ResourceConsumerThread类的实例。 ResourceConsumerThread的run()方法只需调用lambda的方法 - run()。但是,我的要求是传递的lambda i需要引用它传递给它的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()方法中使用它 - 我收到了编译错误。

任何想法如何实现这一点,即使它涉及一些设计返工?主要要求是:

  1. LockManager.acquireLockOnResourceForThread()需要知道哪个ResourceConsumingThread实例正在请求哪个资源。
  2. ResourceConsumingThread的
  3. run()方法应该能够在不同的线程中执行不同的逻辑。
  4. 更新了答案我尝试(不确定它是否正确的做法)。仍然在等待社区潜在解决方案的其他天使。

    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&#39;之后):

     ResourceConsumingThread t = lockManager.createNewThread(() -> {
    
               lockManager.acquireLockOnResourceForThread(new Resource(), (ResourceConsumingThread) Thread.currentThread());
           });
    

2 个答案:

答案 0 :(得分:0)

您可以在匿名内部类中使用this

public void callerMethod(){
ResourceConsumingThread t1 = lockManager.createNewThread(new Runnable() {
            @Override
            public void run() {
                lockManager.acquireLockOnResourceForThread(new Resource(), this);
            }
        });
}

这会将对Runnable中已知的callerMethod的引用传递为t1

答案 1 :(得分:0)

我建议创建一个在其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());
       });