本文介绍了多个线程如何调用单例对象的方法并对其进行处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个正在运行的线程,这些线程访问单例对象并调用其方法并在其中传递对象.在该方法中,我仅对接收到的对象进行一些计算.我听说在这种情况下不会有任何问题,因为它是无状态的,而且对所有人都是免费的.

I have multiple threads running which access singleton object and call its method and pass objects in it. In the method I do some calculations only on recieved object.I have heard that there would not be any problem in this case cause it is stateless and it is free for all.

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

My question is how it is free for all?I want to know how multiple threads can call the shared method in their own thread without overwriting the passed objects of other threads? Please explain in terms of memory allocation wise and at stack level.

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
    }

}

推荐答案

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

I think you have to distinguish between what you've already stored in memory and code execution.

单个对象中,您具有:

  • 字段:它们存储在内存中.它们可以在多个线程之间共享,并且您不能保证它们会保持一致(除非您使它们同步).
  • 要调用的方法:可以从多个线程中调用它们.每次执行都是独立的并且是线程安全的,除非它们不正确地访问某些共享字段.
  • Fields: They are stored in memory. They can be shared amongst multiple threads and you have no guarantee they will keep consistent (unless you make them synchronized).
  • Methods to be called: They can be called from more than one thread. Each execution is independent and thread safe, unless they access some shared field improperly.

现在问您一个问题:如果您在多个线程中共享您的Singleton对象并同时访问它,则每个单个线程都将执行Singleton对象的代码部分,并包装在其自己的执行中.

Now coming to your question: if you share your singleton object among multiple threads and access it concurrently, every single thread will execute Singleton object's portion of code, wrapped in its own execution.

此外,如果您编写的Thread.currentThread().getId();基本返回正在执行的线程ID的单例方法,则将获得不同的ID,因为不同的线程正在执行自己的方法栈. 无状态意味着您没有单身人士可以在其中共享的字段!

Also if you write a Thread.currentThread().getId(); which basically returns the thread ID you're executing into singleton's methods, you will obtain different ids, because different threads are executing their own method stack. Being stateless means you've no fields into the singleton to be shared amongst them!

关于无状态和有状态

无状态表示Bean没有可共享的字段.这意味着您的对象中只有方法或静态对象,因此您可以在任何地方使用它们,并且始终会返回相同的结果.您不必担心同步对字段的访问.

Stateless means that the bean hasn't got any modifiable field to share. That means you have only methods or/and static stuff in your object, so you can use them anywhere and will always return you same result. You don't have to worry about synchronizing the access to the field.

这是有关 stateless 的基本示例,假设您有一个仅执行 sum 操作的类:

That's a basic example about stateless, let's suppose you have a class that only performs the sum operation:

public class StatelessClass{

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

}

以相同的方式,您可以将其声明为抽象类(本身不可实例化),并将其方法设置为 static ,这意味着您不需要任何实例调用它的方法:

In the same way, you can declare it as a abstract class (no instantiable itself) and make its methods static, which means you don't need any instance of it to call its methods:

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中,您在应用程序中共享唯一实例.

Then you can use it as StatelessClass.sum(1,1);, this actually would be very similar to have a Singleton object itself, with the difference that in the Singleton you have a unique instance shared in the application.

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

In the same way, having a field which is injected and provides access to a service neither is considered to alter the state of the object:

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

}

但是,具有可修改的字段会使对象有状态:

However, having a field which is modifiable makes the Object stateful:

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.除非您这样做,否则不能保证印刷出的句子是真实的.

As sum can be accessed by multiple threads at the same time, you should guarantee that totalSum is accessed in a synchronized way. The printed sentence is not guaranteed to be true unless you do it.

此答案的Threadsafety部分中,@ BalusC也对此进行了正确解释.

All of this is also properly explained in this answer's Threadsafety piece by @BalusC.

这篇关于多个线程如何调用单例对象的方法并对其进行处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 21:05