Bot-like Spring Java service for checking advertisements











up vote
4
down vote

favorite












I am in the middle of developing a Spring Boot application, which has a service acting like a bot.



advertisementService.update(Advertisement ad) is a method which parses some HTML. It is important that it cannot execute periodically. For now it is pseudo random, but in the future there will be some logic returning the time depending on information read in previous parsing.



Immediately after the start of the app, it invokes the method scheduleAllChecks().
If a new Advertisement comes up, then it calls scheduleCheck(0, ad);



I am wondering if the solution (I mean the whole service class) is proper and if it can be beter?



package com.gadomski.service;

import com.gadomski.model.Advertisement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
* Created by Krzysiek on 21.08.2016.
*/

@Service
public class CheckerService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final int CHECKER_THREADS = 100;
@Autowired
AdvertisementService advertisementService;
private ScheduledExecutorService scheduledExecutorService;

CheckerService() {
this.scheduledExecutorService = Executors.newScheduledThreadPool(CHECKER_THREADS);
}

public void scheduleCheck(int delaySeconds, Advertisement advertisement) {
if (advertisement.isActive()) {
ScheduledFuture<?> check = this.scheduledExecutorService.schedule(
() -> {
scheduleCheck(getDelayInSeconds(), advertisement);
advertisementService.updateAdvertisement(advertisement);
log.info("Scheaduled next check for " + advertisement.getUrl() + " for user with id: " + advertisement.getUserId());
},
delaySeconds, TimeUnit.SECONDS);
}
}

private int getDelayInSeconds() {
Random rand = new Random();
return (8 + rand.nextInt(10)) * 60 + rand.nextInt(60);
}

public void scheduleAllChecks() {
Random random = new Random();
advertisementService.getAllActvieAdvertisements().forEach(a -> scheduleCheck(random.nextInt(3 * 60), a));
}
}









share|improve this question
























  • Looks like the getAllActvieAdvertisements in the AdvertisementService is spelled incorrectly, but that is all I've got.
    – Ron Beyer
    Nov 16 '16 at 20:15















up vote
4
down vote

favorite












I am in the middle of developing a Spring Boot application, which has a service acting like a bot.



advertisementService.update(Advertisement ad) is a method which parses some HTML. It is important that it cannot execute periodically. For now it is pseudo random, but in the future there will be some logic returning the time depending on information read in previous parsing.



Immediately after the start of the app, it invokes the method scheduleAllChecks().
If a new Advertisement comes up, then it calls scheduleCheck(0, ad);



I am wondering if the solution (I mean the whole service class) is proper and if it can be beter?



package com.gadomski.service;

import com.gadomski.model.Advertisement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
* Created by Krzysiek on 21.08.2016.
*/

@Service
public class CheckerService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final int CHECKER_THREADS = 100;
@Autowired
AdvertisementService advertisementService;
private ScheduledExecutorService scheduledExecutorService;

CheckerService() {
this.scheduledExecutorService = Executors.newScheduledThreadPool(CHECKER_THREADS);
}

public void scheduleCheck(int delaySeconds, Advertisement advertisement) {
if (advertisement.isActive()) {
ScheduledFuture<?> check = this.scheduledExecutorService.schedule(
() -> {
scheduleCheck(getDelayInSeconds(), advertisement);
advertisementService.updateAdvertisement(advertisement);
log.info("Scheaduled next check for " + advertisement.getUrl() + " for user with id: " + advertisement.getUserId());
},
delaySeconds, TimeUnit.SECONDS);
}
}

private int getDelayInSeconds() {
Random rand = new Random();
return (8 + rand.nextInt(10)) * 60 + rand.nextInt(60);
}

public void scheduleAllChecks() {
Random random = new Random();
advertisementService.getAllActvieAdvertisements().forEach(a -> scheduleCheck(random.nextInt(3 * 60), a));
}
}









share|improve this question
























  • Looks like the getAllActvieAdvertisements in the AdvertisementService is spelled incorrectly, but that is all I've got.
    – Ron Beyer
    Nov 16 '16 at 20:15













up vote
4
down vote

favorite









up vote
4
down vote

favorite











I am in the middle of developing a Spring Boot application, which has a service acting like a bot.



advertisementService.update(Advertisement ad) is a method which parses some HTML. It is important that it cannot execute periodically. For now it is pseudo random, but in the future there will be some logic returning the time depending on information read in previous parsing.



Immediately after the start of the app, it invokes the method scheduleAllChecks().
If a new Advertisement comes up, then it calls scheduleCheck(0, ad);



I am wondering if the solution (I mean the whole service class) is proper and if it can be beter?



package com.gadomski.service;

import com.gadomski.model.Advertisement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
* Created by Krzysiek on 21.08.2016.
*/

@Service
public class CheckerService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final int CHECKER_THREADS = 100;
@Autowired
AdvertisementService advertisementService;
private ScheduledExecutorService scheduledExecutorService;

CheckerService() {
this.scheduledExecutorService = Executors.newScheduledThreadPool(CHECKER_THREADS);
}

public void scheduleCheck(int delaySeconds, Advertisement advertisement) {
if (advertisement.isActive()) {
ScheduledFuture<?> check = this.scheduledExecutorService.schedule(
() -> {
scheduleCheck(getDelayInSeconds(), advertisement);
advertisementService.updateAdvertisement(advertisement);
log.info("Scheaduled next check for " + advertisement.getUrl() + " for user with id: " + advertisement.getUserId());
},
delaySeconds, TimeUnit.SECONDS);
}
}

private int getDelayInSeconds() {
Random rand = new Random();
return (8 + rand.nextInt(10)) * 60 + rand.nextInt(60);
}

public void scheduleAllChecks() {
Random random = new Random();
advertisementService.getAllActvieAdvertisements().forEach(a -> scheduleCheck(random.nextInt(3 * 60), a));
}
}









share|improve this question















I am in the middle of developing a Spring Boot application, which has a service acting like a bot.



advertisementService.update(Advertisement ad) is a method which parses some HTML. It is important that it cannot execute periodically. For now it is pseudo random, but in the future there will be some logic returning the time depending on information read in previous parsing.



Immediately after the start of the app, it invokes the method scheduleAllChecks().
If a new Advertisement comes up, then it calls scheduleCheck(0, ad);



I am wondering if the solution (I mean the whole service class) is proper and if it can be beter?



package com.gadomski.service;

import com.gadomski.model.Advertisement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
* Created by Krzysiek on 21.08.2016.
*/

@Service
public class CheckerService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final int CHECKER_THREADS = 100;
@Autowired
AdvertisementService advertisementService;
private ScheduledExecutorService scheduledExecutorService;

CheckerService() {
this.scheduledExecutorService = Executors.newScheduledThreadPool(CHECKER_THREADS);
}

public void scheduleCheck(int delaySeconds, Advertisement advertisement) {
if (advertisement.isActive()) {
ScheduledFuture<?> check = this.scheduledExecutorService.schedule(
() -> {
scheduleCheck(getDelayInSeconds(), advertisement);
advertisementService.updateAdvertisement(advertisement);
log.info("Scheaduled next check for " + advertisement.getUrl() + " for user with id: " + advertisement.getUserId());
},
delaySeconds, TimeUnit.SECONDS);
}
}

private int getDelayInSeconds() {
Random rand = new Random();
return (8 + rand.nextInt(10)) * 60 + rand.nextInt(60);
}

public void scheduleAllChecks() {
Random random = new Random();
advertisementService.getAllActvieAdvertisements().forEach(a -> scheduleCheck(random.nextInt(3 * 60), a));
}
}






java performance spring






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 '16 at 3:25









200_success

128k15149412




128k15149412










asked Nov 16 '16 at 20:00









gadomsky

211




211












  • Looks like the getAllActvieAdvertisements in the AdvertisementService is spelled incorrectly, but that is all I've got.
    – Ron Beyer
    Nov 16 '16 at 20:15


















  • Looks like the getAllActvieAdvertisements in the AdvertisementService is spelled incorrectly, but that is all I've got.
    – Ron Beyer
    Nov 16 '16 at 20:15
















Looks like the getAllActvieAdvertisements in the AdvertisementService is spelled incorrectly, but that is all I've got.
– Ron Beyer
Nov 16 '16 at 20:15




Looks like the getAllActvieAdvertisements in the AdvertisementService is spelled incorrectly, but that is all I've got.
– Ron Beyer
Nov 16 '16 at 20:15










1 Answer
1






active

oldest

votes

















up vote
0
down vote













It appears that you are using Random across multiple threads. I guess you plan to replace it in the future, but still, according to the documentation:




Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.




You should probably rewrite this to use java.util.concurrent.ThreadLocalRandom. As the docs say:




When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention.







share|improve this answer





















  • Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
    – Bogdan Mart
    Oct 9 at 0:12










  • @BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
    – Dair
    Oct 9 at 0:43










  • Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
    – Bogdan Mart
    Oct 9 at 0:59











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f147240%2fbot-like-spring-java-service-for-checking-advertisements%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote













It appears that you are using Random across multiple threads. I guess you plan to replace it in the future, but still, according to the documentation:




Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.




You should probably rewrite this to use java.util.concurrent.ThreadLocalRandom. As the docs say:




When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention.







share|improve this answer





















  • Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
    – Bogdan Mart
    Oct 9 at 0:12










  • @BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
    – Dair
    Oct 9 at 0:43










  • Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
    – Bogdan Mart
    Oct 9 at 0:59















up vote
0
down vote













It appears that you are using Random across multiple threads. I guess you plan to replace it in the future, but still, according to the documentation:




Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.




You should probably rewrite this to use java.util.concurrent.ThreadLocalRandom. As the docs say:




When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention.







share|improve this answer





















  • Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
    – Bogdan Mart
    Oct 9 at 0:12










  • @BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
    – Dair
    Oct 9 at 0:43










  • Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
    – Bogdan Mart
    Oct 9 at 0:59













up vote
0
down vote










up vote
0
down vote









It appears that you are using Random across multiple threads. I guess you plan to replace it in the future, but still, according to the documentation:




Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.




You should probably rewrite this to use java.util.concurrent.ThreadLocalRandom. As the docs say:




When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention.







share|improve this answer












It appears that you are using Random across multiple threads. I guess you plan to replace it in the future, but still, according to the documentation:




Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.




You should probably rewrite this to use java.util.concurrent.ThreadLocalRandom. As the docs say:




When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention.








share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 17 '16 at 7:41









Dair

4,417729




4,417729












  • Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
    – Bogdan Mart
    Oct 9 at 0:12










  • @BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
    – Dair
    Oct 9 at 0:43










  • Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
    – Bogdan Mart
    Oct 9 at 0:59


















  • Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
    – Bogdan Mart
    Oct 9 at 0:12










  • @BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
    – Dair
    Oct 9 at 0:43










  • Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
    – Bogdan Mart
    Oct 9 at 0:59
















Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
– Bogdan Mart
Oct 9 at 0:12




Actually he is creating new instance of Random each time, so there won't be present issue you described, but would be other issue, with calling not so cheap constructor of random each time.
– Bogdan Mart
Oct 9 at 0:12












@BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
– Dair
Oct 9 at 0:43




@BogdanMart I am sorry, but I am not quite sure I understand what you are saying is wrong with my answer. The problem I am addressing is precisely about overhead.
– Dair
Oct 9 at 0:43












Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
– Bogdan Mart
Oct 9 at 0:59




Hmm, I wasn't aware, that ThreadLocalRandom is SIngleton, than it could be used straight instead of random in this case. But my point is that problem is not only in use of Random but also in it's instantiation each time. Proper use case of Random is to store it in variable/class field for later use.
– Bogdan Mart
Oct 9 at 0:59


















draft saved

draft discarded




















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f147240%2fbot-like-spring-java-service-for-checking-advertisements%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Terni

A new problem with tex4ht and tikz

Sun Ra