синхронизированный метод или использовать spring @transactional?

StackOverflow https://stackoverflow.com/questions/1950596

  •  21-09-2019
  •  | 
  •  

Вопрос

У меня есть метод, который будет использоваться для отправки электронной почты.я хочу заблокировать этот метод, чтобы только один поток мог использовать его за раз, а остальные объединялись одновременно.должен ли я синхронизировать метод или использовать spring @transactional PROPAGATION_REQUIRED ?

в моем сервисном слое

 //each time use new thread to send out email
  public  void sendThroughSMTP(List<String> emails,String subject,String content){

            //each time will open and sent through port 25.  dont u think this will caused too many threads spawned?
            BlastEmailThread blastEmailThread = new BlastEmailThread(emails,subject,content);

            blastEmailThread.start();


}
Это было полезно?

Решение

Почему бы не сделать метод потокобезопасным, не используя никаких вещей уровня экземпляра?

Однако я не понимаю, как здесь подходит управление транзакциями Spring.Я имею в виду, что Spring предоставляет несколько менеджеров транзакций, т. е. DataSourceTransactionManager, JtaTransactionManager, HibernateTransactionManager все это связано с сохраняемостью базы данных.Что вы настроите для отправки этого электронного письма?

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

[Добавление]

Когда вы создаете поток для каждого вызова этого метода и не используете ничего из состояния, тогда почему вы хотите создать метод synchronized.Синхронизация метода никоим образом не ограничит количество потоков.Может быть вероятность того, что перед запуском нового потока предыдущий поток, возможно, завершил работу из-за синхронизации.Процесс создания потока может идти медленнее.

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

Другие советы

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

в Sping 3.0 вы можете использовать аннотацию @Async для выполнения задачи, поэтому ваш метод будет выполнен позже и метод будет возвращен напрямую, не дожидаясь отправки электронной почты.

@Async
public  void sendThroughSMTP(List<String> emails,String subject,String content){
//Send emails here, you can directly send lots of email
}

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

Если вы хотите отложить выполнение на определенное время, вы можете использовать аннотацию @Scheduled к вашему методу.

Дополнительное руководство по @Async и @Scheduled можно найти здесь :

http://blog.springsource.com/2010/01/05/task-scheduling-simplifications-in-spring-3-0/

Я не уверен, отвечает ли это на ваш вопрос, но вместо того, чтобы создавать новый поток для каждого письма и вызывать start для него, вы могли бы Исполнитель или Служба исполнителя как член вашего класса, в качестве реализации вы могли бы использовать Потоковый пул - исполнитель с бассейном размером 1.Затем ваш метод sendMail отправит исполняемые файлы исполнителю.

Spring @Transactional не совсем корректно используется в вашем случае.Лучше всего использовать синхронизированный метод и добавить немного пула потоков, если ваш метод вызывается сотнями раз.Но я думаю, вам здесь не нужен пул потоков.

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

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

Сделайте свой сервис singleton и добавить synchronized к вашему методу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top