Java 带单例的ThreadLocal
我正在编写以下代码。两个线程需要它们自己的单实例。线程本地是一个明显的解决方案。但是,我仍然面临使用自己的本地副本运行线程的问题。我在几个java类中有一个场景示例Java 带单例的ThreadLocal,java,multithreading,Java,Multithreading,我正在编写以下代码。两个线程需要它们自己的单实例。线程本地是一个明显的解决方案。但是,我仍然面临使用自己的本地副本运行线程的问题。我在几个java类中有一个场景示例 public class Singleton1 { private int i = 0; private static Singleton1 instance; private Singleton1() { } public static final Singleton1 getInstance() { if (in
public class Singleton1 {
private int i = 0;
private static Singleton1 instance;
private Singleton1() {
}
public static final Singleton1 getInstance() {
if (instance == null) {
instance = new Singleton1();
}
return instance;
}
public int increment() {
return i++;
}
}
public class Holder1 {
private final Singleton1 instance;
public Holder1() {
ThreadLocalSingleton1 singleton1 = new ThreadLocalSingleton1();
instance = singleton1.get();
}
public int increment() {
return instance.increment();
}
private class ThreadLocalSingleton1 extends ThreadLocal<Singleton1> {
@Override
protected Singleton1 initialValue() {
return Singleton1.getInstance();
}
}
}
public class HolderTest {
/**
* @param args
*/
public static void main(String[] args) {
HolderTest test = new HolderTest();
HolderThread thread1 = test.getHolderThread("thread1");
HolderThread thread2 = test.getHolderThread("thread2");
thread1.run();
thread2.run();
}
public HolderThread getHolderThread(String name) {
return new HolderThread(name);
}
private class HolderThread implements Runnable {
String name;
Holder1 holder1 = new Holder1();
public HolderThread(String name) {
this.name = name;
}
@Override
public void run() {
while (true) {
System.out.println(name + " " + holder1.increment());
}
}
}
公共类单音1{
私有整数i=0;
私有静态单例1实例;
私人单音1(){
}
公共静态最终Singleton1 getInstance(){
if(实例==null){
instance=newsingleton1();
}
返回实例;
}
公共整数增量(){
返回i++;
}
}
公共类持有者1{
私人最终单音1例;
公众持股人1(){
ThreadLocalSingleton1 singleton1=新的ThreadLocalSingleton1();
instance=singleton1.get();
}
公共整数增量(){
返回instance.increment();
}
私有类ThreadLocalSingleton1扩展了ThreadLocal{
@凌驾
受保护的Singleton1初始值(){
返回Singleton1.getInstance();
}
}
}
公共类持有者测试{
/**
*@param args
*/
公共静态void main(字符串[]args){
HolderTest测试=新的HolderTest();
HolderThread thread1=test.getHolderThread(“thread1”);
HolderThread thread2=test.getHolderThread(“thread2”);
thread1.run();
thread2.run();
}
public HolderThread getHolderThread(字符串名称){
返回新的HolderThread(名称);
}
私有类HolderThread实现Runnable{
字符串名;
Holder1 Holder1=新的Holder1();
公共保持线程(字符串名称){
this.name=名称;
}
@凌驾
公开募捐{
while(true){
System.out.println(name+“”+holder1.increment());
}
}
}
当ThreadLocalWrappers在Singleton类上调用getInstance时,我不会每次都得到一个新的实例?我如何才能使这项工作符合我的目的
上面的代码是我正在使用的实际代码的一个简单版本。我有单例类,不能将其从单例更改为单例。我正在创建一个测试客户端,该客户端需要作为单个进程运行,但有多个线程。这些线程中的每一个都需要有自己的单例。对多线程使用同步ng
public static synchronized final Singleton getInstance() {
这样,线程将“锁定”该方法:一次只允许一个线程进入该方法,其他线程将阻止该方法,直到该方法被解锁(执行该方法的线程离开)。您将不会遇到这些并发问题
此外,您不需要2个单例(这实际上是毫无意义的,并且违背了单例本身的目的……。使用synchronized进行多线程处理
public static synchronized final Singleton getInstance() {
这样,线程将“锁定”该方法:一次只允许一个线程进入该方法,其他线程将阻止该方法,直到该方法被解锁(执行该方法的线程离开)。您将不会遇到这些并发问题
另外,您不需要2个单例(这实际上毫无意义,并且违背了单例本身的目的……。您的目标类不应该是单例,但您必须仅使用ThreadLocal访问它,如果ThreadLocal实例为空(不包含对目标对象实例的引用),则创建一个新实例
另一种解决方案是将目标类设置为singleton,并将其状态保存在ThreadLocal变量中。目标类不应为singleton,但必须使用ThreadLocal来访问它,如果ThreadLocal实例为空(不保存对目标对象实例的引用),则创建一个新实例
另一个解决方案是将目标类设置为singleton,并将其状态保存在ThreadLocal变量中。您的意思是这样的吗
private static final ThreadLocal<AtomicInteger> COUNTER = new ThreadLocal<AtomicInteger>() {
@Override
protected AtomicInteger initialValue() {
return new AtomicInteger();
}
};
public static int incrementAndGet() {
return COUNTER.get().incrementAndGet();
}
private static final ThreadLocal COUNTER=new ThreadLocal(){
@凌驾
受保护的AtomicInteger初始值(){
返回新的AtomicInteger();
}
};
public static int incrementAndGet(){
返回计数器.get().incrementAndGet();
}
你的意思是这样的吗
private static final ThreadLocal<AtomicInteger> COUNTER = new ThreadLocal<AtomicInteger>() {
@Override
protected AtomicInteger initialValue() {
return new AtomicInteger();
}
};
public static int incrementAndGet() {
return COUNTER.get().incrementAndGet();
}
private static final ThreadLocal COUNTER=new ThreadLocal(){
@凌驾
受保护的AtomicInteger初始值(){
返回新的AtomicInteger();
}
};
public static int incrementAndGet(){
返回计数器.get().incrementAndGet();
}
请看下面的ThreadLocal
工作示例:
public class YourDataHolder {
private static ThreadLocal dataVariable = new ThreadLocal();
private static YourDataHolder dataHolderVar;
private YourDataHolder() { }
public void storeDataToThreadLocal (String userName) {
dataVariable.set(userName);
}
public String readDataFromThreadLocal () {
if (dataVariable.get() != null) {
return (String) dataVariable.get();
}
}
public static ServiceVersionHolder getInstance () {
if (dataHolderVar == null) {
dataHolderVar = new YourDataHolder();
}
return dataHolderVar;
}
}
请看下面的
ThreadLocal
工作示例:
public class YourDataHolder {
private static ThreadLocal dataVariable = new ThreadLocal();
private static YourDataHolder dataHolderVar;
private YourDataHolder() { }
public void storeDataToThreadLocal (String userName) {
dataVariable.set(userName);
}
public String readDataFromThreadLocal () {
if (dataVariable.get() != null) {
return (String) dataVariable.get();
}
}
public static ServiceVersionHolder getInstance () {
if (dataHolderVar == null) {
dataHolderVar = new YourDataHolder();
}
return dataHolderVar;
}
}
你好像被画进了一个角落 一方面,您需要测试现有的代码库,并且代码使用(真正的、正确实现的)单例对象。特别是,在示例类
Singleton1
中将Singleton1()
构造函数声明为private
,使得无法声明子类
另一方面,您的测试要求您编写一个包含大量此类Singleton1
实例的客户机
从表面上看,这是不可能的。无法在JVM中创建两个Singleton1
类的实例,也无法声明Singleton1
的(可编译/可加载)子类
这是每个设计;也就是说,它是Singleton1
类的设计者想要的。(如果不是,那么答案是更改Singleton1
以使其更易于测试。例如,通过使Singleton1
构造函数不私有
,以便可以为测试目的创建多个实例。)
(例如,当前实现ThreadLocalSingleton1
的尝试失败,因为Singleton1.getInstance()
返回Singleton1
的全局实例。无论您做什么,都无法创建Singleton1
类的任何其他实例。)
然而,我可以为您的特定用例想出两种变通方法
我正在编写一个需要