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.