In my contrived example, what are the implications for thread safety with regard to the list of teamMembers?
Can I rely on the state of the list as seen by the run()
method to be consistent?
Assuming
the setATeamMembers
method is called only once, by spring when it is creating the ATeamEpisode
bean
the init
method is called by spring (init-method) after #1
the ATeamMember
class is immutable
Do I need to declare the teamMembers
volatile
or similar?
Are there any other hideous problems with this approach that I'm overlooking?
Apologies if this is obvious, or a clear failure to rtfm
Thanks and regards
Ed
package aTeam;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ATeamEpisode implements Runnable{
private List<ATeamMember> teamMembers;
/* DI by spring */
public void setATeamMembers(List<ATeamMember> teamMembers){
this.teamMembers = new ArrayList<ATeamMember>(teamMembers);
}
private Thread skirmishThread;
public synchronized void init(){
System.out.println("Starting skirmish");
destroy();
(skirmishThread = new Thread(this,"SkirmishThread")).start();
}
public synchronized void destroy(){
if (skirmishThread != null){
skirmishThread.interrupt();
skirmishThread=null;
}
}
private void firesWildlyIntoTheAir(ATeamMember teamMember){
System.out.println(teamMember.getName()+" sprays the sky..");
}
@Override
public void run() {
try {
Random rnd = new Random();
while(! Thread.interrupted()){
firesWildlyIntoTheAir(teamMembers.get(rnd.nextInt(teamMembers.size())));
Thread.sleep(1000 * rnd.nextInt(5));
}
} catch (InterruptedException e) {
System.out.println("End of skirmish");
/* edit as per Adam's suggestion */
// Thread.currentThread().interrupt();
}
}
}
No spring object is not thread safe . You have to manage it. For scope thread different service bean is created for every new thread request to service.
You should not worry about thread safety of the dependency injection, Spring does (most likely, spring is going to use just one thread to inject all the dependencies).
So YES, Spring MVC classes must be thread safe. You can do this by playing with different scopes for your class instance fields or just having local variables instead. Failing that, you'll need to add appropriate synchronization around critical sections in your code.
If there is any global variable defined the singleton class then it will not be thread safe because if multiple thread share the singleton object and execute the method which can updates the global variable it will not be thread safe.
If, as you say, setATeamMembers is called only once, and no other part of your code either replaces this collection, then there is no point in making it volatile. Volatile indicates that a member can be written by different threads.
Considering no part of your code seems to be updating this collection either, you might want to consider making the collection explicitly unmodifiable, for instance by using Collections.unmodifiableList(). This makes it clear to you, and others, that this collection won't be modified, and will throw a big fat exception in your face if you try to modify it regardless.
Spring's lazy initialization is, AFAIR, thread safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With