简体   繁体   中英

Java: give access for created objects to a shared resource

The situation before:

A Resource exists. Class Root is created, and during it's creation it creates Child classes (many implementations of one base). Those can, but don't have to, posses children. Basically, this is a typical tree structure, that builds itself.

One of the Child classes "NeedyChild" requires access to a Resource that was opened during creation of Root. There was only one Resource possible, so I made it a singleton and accesed it from NeedyChild by Resource.getInstance();

The situation now:

I have to build many trees. Those are independent of each other and take quite some time, so I made it concurrent. Unfortunatelly, each tree has it's own Resource.

Question: how to access the Resource specific to the current runnable now?

My solutions:

  1. Make Child base class require Resource parameter in it's constructor. Pros: it's quick. It's fairly efficient (passing a reference is no big deal), it's simple. Cons: it requires me to change constructor calls and signatures throughout the application, possibly >100 places.

  2. Reflection to make base constructor find it's caller, save reference, then just give Resource to Root, and NeedyChild will go up "creators" hierarchy to get Root and then Resource. But I won't do that, it's evil.

  3. Didn't research it, but maybe I can access the parent Runnable the code is currently executing inside? Cast it back to my RunnableClass which could hold reference to Resource? The problems are: I don't know if it's possible, it seems a bit "wrong" too...

  4. (not really working) Make the tree traversable both ways, give Resource to Root and from NeedyChild getParent() long enough until you're at Root. It would be great, but the NeedyChild needs Resource during it's creation, and only after it is created, it is appended to the parent. I thought of delaying filling Resource-dependent fields, but it gets ugly very quick.

TBH I probably will have to modify the base constructor and either pass "this" (so I can traverse back to the Root), or pass Resource. The runnable-specific context seems also quite decent, but I'm already doing the parallel procesing to make things faster, I don't really want to negate it by some very slow reflection lookups...

So, any ideas?

Addendum 1: Sample Code

abstract class BaseElement{
    List<BaseElement> children = new ArrayList<>();

    public void addChild(BaseElement child){
        children.add(child);
    }
}

class Loader{
    private PackageElement resultPackage;
    private Resource resource;

    public Loader(Resource resource){
        this.resource = resource;
    }

    public callMeFromOutside(SourceTree source){
        resultPackage = new Package(source.pack());
    }
}

class PackageElement extends BaseElement {
    public PackageElement(PackageTree pack){
        this.addChild(new Element(pack.element()));
    }
}

class Element extends BaseElement{
    public Element(ElementTree element){
        this.addChild(new NeedyChild(element.needyChild()));
    }
}

class NeedyChild extends BaseElement{
    public NeedyChild(NeedyTree needy){
        this.setSomethingImportant(resource.loadSomethingBasedOn(needy));
    }
}

Since there is a one-to-one correspondence between a tree and thread, modifying your singleton pattern to be thread-local should do the trick. For concreteness, here is a code sample:

public class Resource
{
    private static final ThreadLocal<Resource> threadLocal = new ThreadLocal<Resource>();

    public static Resource getInstance()
    {
        return threadLocal.get();
    }

    public static void setInstance(final Resource instance)
    {
        threadLocal.set(instance);
    }
    ...
}

Just make sure that you call Resource.setInstance on the appropriate thread before instantiating NeedyChild objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM