在Java中,每个线程可能有Singleton吗?

时间:2011-05-20 00:31:04

标签: java multithreading singleton

使用线程,我有一个主要类(SlaveCrawler),它实例化三个类(Downloader, ContentAnalyzer, URLAnalyzer),它们相互依赖。

SlaveCrawler使用DownloaderURLAnalyzer

Downloader使用ContentAnalyzerURLAnalyzer

ContentAnalyzer使用URLAnalyzer

我只想要每个类的一个实例。如果我使用Singleton,我可以得到这个,但是使用线程,我将有20 SlaveCrawlers(示例),所以我想要20 URLAnalyzer

有可能使用Singleton或我需要其他方式吗?

4 个答案:

答案 0 :(得分:21)

看看ThreadLocal。每个线程都有自己的每个对象的本地副本。

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

或者在1.8中我们可以使用:

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

要访问ThreadLocal对象,请使用get()方法。

YourObject yourObject = threadLocalYourObject.get();

答案 1 :(得分:4)

您可以使用ThreadLocal实现它。 这是伪代码:

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();方法将返回与当前线程相关的对象。如果没有关联对象,则调用protected MyTLSingleTon initialValue()方法并设置新实例。

答案 2 :(得分:2)

是。这是可能的。

在/“返回单例”的方法中(例如getInstance()),使用线程局部存储来检查(并在需要时创建)要返回的单例对象的实例。

然而,这个听起来很混乱。考虑到不使用“单一模式”;而是根据需要传递相同的对象(或考虑使用DI框架)。

快乐的编码。

答案 3 :(得分:-1)

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;
    }
}