Как singleton Bean обслуживает одновременный запрос?

У меня вопрос о том, как синглтон-бины подробно обслуживают параллельные запросы.

Я искал в StackOverflow этот вопрос. Это образец ссылки из stackoverflow, но я нашел только подробности высокого уровня. Мне нужна полная информация о том, как одноэлементный компонент обслуживает параллельные запросы и как системный процессор будет видеть эти запросы.

Я исследовал одновременную обработку запросов в системном процессоре в Интернете. Они сказали, что у самого процессора есть планировщик, и этот планировщик решит, какой запрос будет обработан.

Хорошо. Если предположить, что у меня более одного базового процессора, как планировщик обрабатывает одновременные запросы?

Может ли кто-нибудь объяснить мне пошаговый процесс того, как одноэлементный компонент будет обслуживать одновременные запросы в JVM и системе?

Поясню на конкретном примере. У меня есть класс типа Sports:

class Sports {
    public void playFootball() {
    }

    public void playVolleyBall() {
    }
}

Входят два запроса. Первый запрос выполняет метод playFootball для созданного одноэлементного экземпляра класса Sports. В то же время другой запрос выполняет метод playVolleyBall для того же созданного экземпляра синглтона класса Sports.

Как это возможно с экземпляром singleton?


person saravanakumar    schedule 02.09.2014    source источник
comment
Нет в этой ссылке ответ на этот вопрос неверен. В этом случае пользователь спрашивает, как одноэлементный компонент обслуживает параллельный запрос, но он дал ответ, как сделать одноэлементный компонент потокобезопасным. Здесь я не спрашиваю, как сделать одноэлементный bean-компонент потокобезопасным. Я хочу знать логику того, как одноэлементный компонент обслуживает одновременный запрос?   -  person saravanakumar    schedule 02.09.2014


Ответы (6)


Сараван Кумар,

Я понимаю мотивацию вашего вопроса. До того, как я начал работать над компиляторами, у меня также было очень похожее желание узнать внутреннее устройство виртуальной машины Java.

Прежде всего, меня впечатлил ваш вопрос. Чтобы решить ваш вопрос, необходимо несколько отличий и понимания. Во-первых: шаблон Singleton, или иногда даже называемый анти-шаблоном, гарантирует, что существует только один экземпляр этого класса, доступный для JVM (виртуальной машины Java). Это означает, что мы, по сути, вводим глобальное состояние в приложение. Я знаю, что вы это понимаете, но это просто уточнение.

Теперь о внутренностях.

Когда мы создаем экземпляр класса, мы создаем объект, который находится в общей памяти JVM. Теперь эти потоки независимо выполняют код, работающий с этими экземплярами. Каждый поток имеет рабочую память, в которой хранятся данные из основной памяти, которые совместно используются всеми потоками. Здесь находится ссылка на созданный вами объект Singleton. По сути, происходит то, что сгенерированный байт-код, представляющий созданный вами одноэлементный объект, выполняется в каждом из этих потоков.

Теперь внутреннее устройство того, как это происходит, выглядит следующим образом:

Каждый поток JVM имеет частный стек JVM, созданный одновременно с потоком. Теперь у JVM есть куча, которая используется всеми потоками JVM. Куча - это область данных времени выполнения, из которой выделяется память для всех экземпляров классов и массивов. Куча создается при запуске виртуальной машины. Когда ваш поток запрашивает экземпляр синглтона, он будет указывать на ссылку в куче, где находится байт-код для этого синглтона. Собирается выполнить соответствующий код. В вашем случае он будет выполнять первый метод для первого запроса и второй метод для второго запроса. Это возможно, потому что нет никаких блокировок или ограничений, мешающих компилятору указывать счетчик программы на область в куче, где размещен этот экземпляр. Единственное ограничение, которое класс Singleton накладывает на виртуальную машину Java, состоит в том, что он может иметь только один экземпляр в куче этого класса. Это просто так. Помимо этого, вы можете ссылаться на него 100 раз из своего метода, компилятор укажет на тот же байт-код и просто выполнит его. Вот почему мы обычно хотим, чтобы класс Singleton не имел состояния, потому что, если у нас какой-либо поток обращается к нему, мы не хотим, чтобы внутренние переменные изменялись из-за отсутствия контроля параллелизма.

Пожалуйста, дай мне знать, если возникнут какие-либо вопросы!

person Devarsh Desai    schedule 03.09.2014
comment
Большое спасибо за ваше объяснение. Теперь у меня все ясно, и я дам вам знать, если у меня возникнут какие-либо сомнения. - person saravanakumar; 03.09.2014
comment
Рад слышать Саравана Кумара! : 0) Пожалуйста, обращайтесь к нам, если возникнут какие-либо вопросы! - person Devarsh Desai; 03.09.2014
comment
@Devarsh Desai хорошее объяснение ... +1 - person Ashish Jagtap; 04.09.2014
comment
@ 157. Вы что-нибудь знаете о GWT. теперь у меня есть небольшое требование в моем приложении GWT. могли бы вы увидеть мое сообщение здесь stackoverflow.com/questions/26654031/ - person saravanakumar; 30.10.2014
comment
Хорошо сказал @Dev. - person Arun; 22.11.2017

Идеальный одноэлементный компонент не должен сохранять никакого состояния. Это означает, что у него не будет никаких переменных, которые хранят что-либо, относящееся к обслуживаемому запросу.

Таким образом, одноэлементный компонент будет просто иметь код без состояния (например, методы контроллера), который может выполняться одновременно для нескольких запросов без каких-либо проблем с параллелизмом.

Например, если ниже был ваш singleton bean:

@Service
public class Calculator {

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

}

Проще говоря, когда два «запроса» вызывают sum метод компонента одновременно, это будет означать, что метод sum будет выполняться одновременно в двух разных потоках. Следовательно, у них будет свой собственный контекст выполнения, который не будет перекрываться друг с другом. Это безопасно позволило бы им работать одновременно.

Если один и тот же bean-компонент должен иметь следующее состояние:

@Service
public class Calculator {

   int incrementalMultiplier = 0;

   public int mulitply(int a, int b) {
        incrementalMultiplier++;
        return a * b * incrementalMultiplier;
   } 

}

Это может вызвать проблемы при одновременном обслуживании двух запросов, поскольку incrementalMultiplier - это состояние уровня объекта, которое будет совместно использоваться двумя запросами (потоками) и, следовательно, может привести к неожиданным результатам.

Короче говоря, синглтон без сохранения состояния сможет обслуживать два запроса одновременно, потому что они будут находиться в разных потоках.

person Varun Phadnis    schedule 02.09.2014
comment
Действительно, и я хочу знать, как этот компонент без сохранения состояния обслуживает одновременный запрос? - person saravanakumar; 02.09.2014
comment
Пытался объяснить это поподробнее простыми словами ... дайте мне знать, что это помогает. :) - person Varun Phadnis; 02.09.2014
comment
Да, потоки имеют свою собственную стековую память, и они сохранят имя метода и переменную метода для каждого потока индивидуально. Если контекст выполнения будет разным для каждого запроса, как один и тот же bean-компонент будет обслуживать два разных контекста в одно и то же время? - person saravanakumar; 02.09.2014
comment
Когда вы думаете на уровне выполнения потоков, методы bean-компонента просто превращаются в некоторый код, который нужно выполнить. Как вы думаете, почему два потока не могут выполнять один и тот же код одновременно? Поскольку они находятся в своем собственном контексте и изолированы, это немного похоже на то, что одна и та же программа запускается на двух разных компьютерах. - person Varun Phadnis; 02.09.2014
comment
Да, это должно быть выполнено. Я спрашиваю, какова логика за экраном. Как они выполняют две разные или одинаковые работы с одним компонентом. Теперь у меня есть кое-что, но извините, я все еще не понимаю. Не могли бы вы подробно объяснить мне, как электрический человек (одноэлементный компонент) будет выполнять одну и ту же работу (метод) одновременно в другом месте (контекст выполнения потока)? - person saravanakumar; 02.09.2014
comment
Компонент не выполняет никакой работы - два потока одновременно выполняют тело кода, определенное в компоненте. Я подозреваю, что вы этого не понимаете, поскольку ваше базовое понимание CS не очень ясное. Я бы посоветовал перейти к основным понятиям. Понять, что именно происходит при выполнении кода. - person Varun Phadnis; 02.09.2014
comment
Спасибо за ваше время и прекрасное объяснение. И ваши подозрения верны. Я не так уж силен в основах CS. Потому что в основном я инженер-электрик, но теперь я инженер-программист. - person saravanakumar; 03.09.2014
comment
Отличное объяснение !! - person Abhishek Kumar; 09.12.2020

Чтобы узнать в деталях Как одноэлементный компонент Bean обслуживает одновременный запрос? вы должны знать следующее о Spring Beans

  • Области действия компонентов

    Spring имеет разные области действия bean-компонентов (например, Prototype, Singleton и т. Д.), Но все эти области применяются при создании bean-компонента. Например, bean-компонент с областью видимости «прототип» будет создаваться каждый раз, когда этот bean-компонент «вводится». в то время как bean-компонент с одноэлементной областью видимости будет создан один раз и совместно используется в контексте приложения.
    «singleton» с областью видимости по умолчанию является областью Spring Bean.

  • Создание Bean

    Весь жизненный цикл Spring Bean управляется контейнером Spring (т.е. ApplicationContext / BeanFacotry). Spring Container внутренне ссылается на определение bean-компонента (то есть на базе XML или на основе аннотации) для создания фактических экземпляров класса, определенного этим определением bean-компонента. теперь, когда Spring Container запускается, он обращается к определению bean-компонента и инсталлирует весь определенный bean-компонент.

  • Запросить компонент.

    Теперь, когда ваш объект делает запрос к bean-компоненту, Spring Container передает bean-компонент, который уже инициализирован.

  • Spring Bean Scope

  • Являются ли объекты Spring потокобезопасными?

  • Spring Tutorial 11 - Understanding Bean Scopes < / сильный>

Надеюсь, что это поможет вам...

person Ashish Jagtap    schedule 02.09.2014
comment
Да, правильно, и спасибо за ответ, но я не видел никаких объяснений по поводу моего вопроса (как singleton Bean обслуживает одновременный запрос?) В приведенном выше ответе. - person saravanakumar; 02.09.2014
comment
для каждого запроса к одноэлементному контейнеру Bean будет предоставлен компонент, который уже был инициализирован во время запуска контейнера. - person Ashish Jagtap; 02.09.2014
comment
для каждого запроса к одноэлементному контейнеру Bean будет предоставлен тот же bean, который уже был инициализирован во время запуска контейнера, и как он будет предоставлять тот же bean во время параллельного запроса? и как один и тот же bean-компонент будет выполнять одинаковую работу (один и тот же метод в классе) или другую работу (другой метод в одном классе) в параллельном запросе? - person saravanakumar; 02.09.2014

Я видел множество советов о том, чтобы разделяемые одноэлементные бины не имели состояния, и хотел представить пример использования, в котором одноэлементный объект с сохранением состояния в поддерживающем бине веб-приложения имеет смысл.

У меня есть административное веб-приложение, которое по запросу запрашивает данные пользователя в двух отдельных системах (CRM и Digital Assets Manager - DAM), сравнивает записи и соответственно обновляет DAM, используя свой API. Иногда это занимает очень много времени, если обновлений много. Веб-интерфейс отображает состояние обновлений в реальном времени, поскольку браузер каждую секунду опрашивает компонент поддержки, используя ajax, чтобы отобразить индикатор выполнения и количество учетных записей пользователей, которые он обработал. Пользовательский интерфейс также предоставляет кнопку для запуска процесса синхронизации и кнопку для его остановки. Кнопка синхронизации изначально включена, а кнопка остановки не отображается. После того, как пользователь нажимает кнопку «Пуск», кнопка «Пуск» отключается, а кнопка «Стоп» становится активной.

Пока синхронизация активна, я хочу, чтобы разные клиенты (разные пользователи с клавиатурой, использующие веб-приложение в своих отдельных браузерах) видели одно и то же состояние, то есть индикатор выполнения, количество обработанных учетных записей пользователей и состояния кнопок. Это важно, потому что нет смысла запускать второй процесс синхронизации, пока он уже выполняется.

person snakedog    schedule 24.08.2017

Этому вопросу уже 5+ лет (2019 г.), и я надеюсь, что вы нашли то, что ищете. но я все равно отправлю ответ. это может не только ответить на ваш вопрос, но и вкратце описать многопоточное поведение.

прежде всего. синглтон - это шаблон проектирования, используемый в программировании, который используется для создания только одного экземпляра для всего приложения (только один для JVM. Я надеюсь, что в вашем приложении только одна JVM). многопоточность - это механизм обработки. он выполняет задачи одновременно. Я думаю, вы запутались, потому что вы уже знаете, что поток является логическим местом обработки. а объект - это экземпляр памяти. но вы не понимали, как на самом деле работает многопоточность. Что касается вашего вопроса, я объясню это с помощью Spring Framework.

поэтому, когда пользователь отправляет запрос на сервер, сервер выделяет отдельный поток для каждого запроса. а весной бины по умолчанию являются одноэлементными. поэтому первый запрос начинает выполнять метод вашего одноэлементного bean-компонента, а до его завершения приходит другой запрос, который выполняет тот же метод, используя другой поток.

Итак, здесь происходит то, что второй поток не будет ждать, пока первый закончит выполнение всего метода. они выполняются одновременно, это означает, что первый запрос будет запускать первую строку метода, а затем второй поток начинает выполнять первую строку. и, возможно, вторая линия тоже. Обратите внимание, что в то время как первый поток выполняет первую строку, второй поток не может выполнять ту же строку, и пока второй выполняет первую строку и вторую строку, первый не может выполнять вторую строку, пока второй поток не закончит вторую строку.

хотя мы называем это одновременным выполнением, оно вообще не выполняется одновременно. (одна строка выполняется только одним потоком одновременно) в соответствии с вашим вопросом вы определяете два метода в bean-компоненте, поэтому они являются отдельными методами. поэтому два потока, запрашивающие два метода одновременно, будут выполнять их одновременно. поэтому то, что я описал, не применимо к этому сценарию, и если ваши bean-компоненты создаются заново для каждого запроса, то этого также не произойдет, и они будут выполняться одновременно.

person Tharindu Eranga    schedule 23.12.2019
comment
Ваш второй последний абзац напоминает мне фильм. Хорошая попытка! - person Ram; 05.07.2021
comment
@ Ram, да, параллелизм сложно объяснить, используя только тексты. - person Tharindu Eranga; 07.07.2021

Синглтон - это бин-область видимости. Вы должны справиться с этим, как обслуживать многопоточный доступ. Вы можете использовать синхронизацию или одновременные пакеты. Ссылка: Являются ли одноэлементные bean-компоненты Spring потокобезопасными?

При параллельном запросе один компонент будет обслуживать несколько запросов один за другим.

person CHowdappaM    schedule 02.09.2014
comment
Если одноэлементный компонент будет обслуживать параллельные запросы поочередно, тогда почему мы идем на синхронизацию, потому что запросы будут обрабатываться один за другим. Я прав ? - person saravanakumar; 02.09.2014
comment
Параллельный запрос начинает вызов метода один за другим (хотя это тоже не совсем правильно), но выполнение может быть прервано, так что новый поток начнет вызов того же метода. Проблема в том, что если bean-компонент является одноэлементным, используется один и тот же экземпляр, и два выполнения видят одни и те же поля одноэлементного объекта; может случиться (и бывает), что при первом выполнении вы устанавливаете значение поля, затем получаете приоритетное значение и запускаете второй вызов. Если второй вызов изменяет значение этого поля, первый затем считывает измененные значения. - person Dan M; 02.09.2014
comment
@Dan M Да, действительно. но в этом я не сомневаюсь. У моего bean-компонента нет НИКАКОГО СОСТОЯНИЯ, и он объявлен как FINAL, чтобы сделать его потокобезопасным bean-компонентом. Я сомневаюсь, как один и тот же bean (Singleton bean) в одно и то же время будет обслуживать два или более запроса? - person saravanakumar; 02.09.2014