多个线程如何调用单例对象的方法并对其进行处理?



我有多个线程在运行,它们访问singleton对象并调用其方法并在其中传递对象。在该方法中,我只对接收的对象进行一些计算。我听说在这种情况下不会有任何问题,因为它是无国籍的,对所有人都是免费的。

我的问题是,它如何对所有人免费?我想知道多个线程如何在自己的线程中调用共享方法,而不覆盖其他线程传递的对象?请按照内存分配和堆栈级别进行解释。

class Singleton class{
    //no shared class or object variables and only one copy of this Singleton object exists.
    Object someMethod(Object o){
        //do some calculation or logic on the object o and return some string result
    }
}

我认为您必须区分已经存储在内存中的内容和代码执行。

Singleton对象中,您有:

  • 字段:它们存储在内存中。它们可以在多个线程之间共享,并且不能保证它们保持一致(除非您使它们同步
  • 要调用的方法:可以从多个线程调用它们。每次执行都是独立的且线程安全的,除非它们不正确地访问某些共享字段

现在来谈谈您的问题:如果您在多个线程之间共享singleton对象并同时访问它,那么每个线程都将执行singleton的代码部分,并封装在自己的执行中。

此外,如果您编写一个Thread.currentThread().getId();,它基本上将您正在执行的线程ID返回到singleton的方法中,您将获得不同的ID,因为不同的线程正在执行自己的方法堆栈。无状态意味着您在singleton中没有要在它们之间共享的字段!

关于无状态和有状态的单词

无状态意味着bean没有任何可修改的字段可以共享。这意味着您的对象中只有方法或/和静态内容,所以您可以在任何地方使用它们,并且总是会返回相同的结果。您不必担心同步对字段的访问。

这是关于无状态的一个基本示例,假设您有一个只执行sum操作的类:

public class StatelessClass{
    public int sum(int a, int b){
        return a+b;
    }
}

同样,您可以将其声明为抽象类(本身不可实例化),并使其方法为静态,这意味着您不需要它的任何实例来调用其方法:

public abstract class StatelessClass{
    /**
    *   I only sum objects
    */
    public static int sum(int a, int b){
        return a+b;
    }
}

然后您可以将其用作StatelessClass.sum(1,1);,这实际上与拥有Singleton对象本身非常相似,不同之处在于在Singleton中,您在应用程序中共享了一个唯一的实例。

以同样的方式,具有一个被注入并提供对服务的访问的字段既不被认为会改变对象的状态:

public class StatelessServiceClass{
    private Service service;
    public int sum(int a, int b){
        return service.sum(a,b);
    }
    public void setService(Service serv){
        this.service=serv;
    }
}

但是,有一个可修改的字段会使Object有状态

public class StatefulClass{
    //This fields make the object STATEFUL
    private int totalSum = 0;
    public int sum(int a, int b){
        int sum = a + b;
        totalSum = totalSum + sum;
        if (totalSum > 100)
            System.out.println("This thread "+Thread.currentThread().getId()+
                +" got it!");
        return sum;
    }
}

由于sum可以由多个线程同时访问,因此应确保以同步的方式访问totalSum。除非你这么做,否则打印出来的句子不能保证是真的

所有这些也在@BalusC的Threadsafety文章中得到了恰当的解释。

每个线程都有自己的Object o副本,因此即使多个线程同时调用该方法,thread的每个方法调用都将分配其自己的堆栈,并且逻辑将在那里应用。

为什么它是线程安全的

线程堆栈对它们来说是私有的,默认情况下是线程安全的,因为没有其他线程可以进入其他堆栈。

注意:您可以说您的Singleton是线程安全的,但不能说应用程序是线程安全,因为它还取决于传递的Object o本身是否是线程安全。但就辛格尔顿的安全性而言,它是线程安全的。

你可以用"披萨术语"来思考它。你去了披萨店,其他几个人也和你一起进去了。每个人都点了菜,然后坐到自己的桌子旁。披萨盒到了,你们每个人都开始吃自己的饭。

在这里,咖啡馆是一个单体,披萨男孩是CPU核心,你和其他顾客是线程,订单和披萨分别是输入和输出数据,表是一块内存。

正如您所看到的,每个线程都有自己的内存,这样CPU就可以区分您的数据,而不会混淆。正如您所问的堆栈,它在这里并不是一个重要的参与者,因为每个线程都有自己的堆栈(作为内存块的一部分)。

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    public class MainClass {
        public final static int MAX_THREAD = 20;
        public MainClass() {
            // TODO Auto-generated constructor stub
        }
        public static void main(String[] args) {
            List<Singleton> singletonList = new MainClass().createSingletonObjects();
            singletonList = Collections.synchronizedList(singletonList); 
            int index = 0;
            for (int i = 0; i < MAX_THREAD; i++) {
                Thread thread1 = new Thread(new MyThread(singletonList,index), "Thread"+i);
                thread1.start();
                index++;
            if (index == singletonList.size()) {
            index = 0;  
            }
            }
        }
    public synchronized List<Singleton> createSingletonObjects(){
        List<Singleton> listSingleton = new ArrayList<Singleton>();
            listSingleton.add(MySingleton1.getInstance());
            listSingleton.add(MySingleton2.getInstance());
            listSingleton.add(MySingleton3.getInstance());
            listSingleton.add(MySingleton4.getInstance());
            listSingleton.add(MySingleton5.getInstance());
            return listSingleton;
        }
    }

public class MySingleton1 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton1() {
        super();
        // TODO Auto-generated constructor stub
    }
    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton1();
            return mySingleton;
        }
        return mySingleton;
    }

public class MySingleton2 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton2() {
        super();
        // TODO Auto-generated constructor stub
    }
    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton2();
            return mySingleton;
        }
        return mySingleton;
    }



}

public class MySingleton3 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton3() {
        super();
        // TODO Auto-generated constructor stub
    }
    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton3();
            return mySingleton;
        }
        return mySingleton;
    }



}

public class MySingleton4 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton4() {
        super();
        // TODO Auto-generated constructor stub
    }
    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton4();
            return mySingleton;
        }
        return mySingleton;
    }



}

public class MySingleton5 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton5() {
        super();
        // TODO Auto-generated constructor stub
    }
    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton5();
            return mySingleton;
        }
        return mySingleton;
    }



}

最新更新