简体   繁体   中英

In Java, it's possible Singleton per thread?

Using threads, I have a principal class ( SlaveCrawler ) that instantiates three classes( Downloader, ContentAnalyzer, URLAnalyzer ) , which are dependent on each other.

SlaveCrawler uses Downloader and URLAnalyzer

Downloader uses ContentAnalyzer and URLAnalyzer

ContentAnalyzer uses URLAnalyzer

I want only one instance of each class. If I use Singleton , I can get this, but working with threads, I will have 20 SlaveCrawlers (example), so I want 20 URLAnalyzer .

It's possible make this using Singleton or I need other way?

Take a look at ThreadLocal . Each thread will have its own local copy of each object.

ThreadLocal<YourObject> threadLocalYourObject = new ThreadLocal<YourObject>() {
  @Override
  protected YourObject initialValue() {
    //initialize YourObject
  }
}

Or in 1.8 we can use:

ThreadLocal<YourObject> threadLocalYourObject = ThreadLocal.withInitial( () -> new YourObject() )

To get access to your ThreadLocal object, use the get() method.

YourObject yourObject = threadLocalYourObject.get();

You can implement it with ThreadLocal. Here is the pseudo code:

public class ThreadLocalTest {

  public static void main(String[] args){
    MyTLSingleTon obj = MyTLSingleTon.getInstance();
  }

}

class MyTLSingleTon{

  private MyTLSingleTon(){  
  }

  private static final ThreadLocal<MyTLSingleTon> _localStorage = new ThreadLocal<MyTLSingleTon>(){
    protected MyTLSingleTon initialValue() {
      return new MyTLSingleTon();
   }
  };

  public static MyTLSingleTon getInstance(){
    return _localStorage.get();
  }
}

MyTLSingleTon.getInstance(); method will return an object assosiated with the current thread. and if no object is assosiated than protected MyTLSingleTon initialValue() method will be called and a new instance will be set.

Yes. This is possible.

In a/the method "which returns the singleton" (eg getInstance()), use thread-local storage to check for (and create if needed) an instance of the singleton object to return.

However, this sounds quite messy . Consider just not using a "singleton pattern" for this; but rather pass the same object about as required (or consider using a DI framework).

Happy coding.

I have used the implementation as explained above, I am able to achieve the single object per thread.
Below is my complete implementation

package example.test;

public class ThreadLevelSingleton
{
    public static void main(String[] args)
    {
        Thread33 t3 = new Thread33();
        t3.run();

        Thread44 t4 = new Thread44();
        t4.run();

        MySingleTon m1 = MySingleTon.getInstance();
        MySingleTon m2 = MySingleTon.getInstance();

        System.out.println(Thread.currentThread().getName() + " : " + (m1 == m2));

        MySingleTon tm1 = t3.getMySingleTon();
        MySingleTon tm2 = t4.getMySingleTon();
        System.out.println(Thread.currentThread().getName() + " : " + (tm1.equals(tm2)));
    }
}

class MySingleTon
{
    private MySingleTon()
    {
    }

    private static final ThreadLocal<MySingleTon> t = new ThreadLocal<MySingleTon>()
    {
        @Override
        protected MySingleTon initialValue()
        {
            return new MySingleTon();
        }
    };

    public static MySingleTon getInstance()
    {
        return t.get();
    }
}

class Thread33 extends Thread
{
    MySingleTon m1;

    @Override
    public void run()
    {
        MySingleTon t = MySingleTon.getInstance();
        MySingleTon t1 = MySingleTon.getInstance();
        m1 = MySingleTon.getInstance();
        System.out.println(getName() + " : " + (t == t1));
        System.out.println(t);
        System.out.println(t1);
    }

    MySingleTon getMySingleTon()
    {
        return m1;
    }
}

class Thread44 extends Thread
{
    MySingleTon m1;

    @Override
    public void run()
    {
        MySingleTon t = MySingleTon.getInstance();
        MySingleTon t1 = MySingleTon.getInstance();
        m1 = MySingleTon.getInstance();
        System.out.println(getName() + " : " + (t == t1));
        System.out.println(t);
        System.out.println(t1);
    }

    MySingleTon getMySingleTon()
    {
        return m1;
    }
}

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