[문제코드]
@Service
public class MemberServiceImpl{
@Autowired
private UserRepository userRepository;
private Member member = new Member();
public void createUser(String id, String name) throws Exception {
member.setID(id);
member.setName(name);
userRepository.insertUser(member);
}
}
[해결 코드]
@Service
public class MemberServiceImpl{
@Autowired
private UserRepository userRepository;
public void createUser(String id, String name) throws Exception {
Member member = new Member();
member.setID(id);
member.setName(name);
userRepository.insertUser(member);
}
}
Singleton 의 경우 멀티스레드 환경에서 static이 아니여도 멤버변수의 값이 공유될수 있다. (스레드에 안전하지 않다.)
public class Member {
String id;
String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class StaticMethodMultiThreadTest {
public static void main(String arg[]) {
int exeCnt = 100;
for (int i = 0; i < exeCnt; i++) {
new Thread(new TestThreadClass()).start();
}
}
}
class TestThreadClass extends Thread {
static int i = 1;
public void run() {
if(i%2 == 0) {
TestThreadClass2 t2 = TestThreadClass2.getInstance();
t2.testStaticMethod(this.getName());
}else{
TestThreadClass2 t2 = TestThreadClass2.getInstance();
t2.testStaticMethod2(this.getName());
}
i++;
}
}
public class TestThreadClass2 {
private static TestThreadClass2 uniqueInstance;
private TestThreadClass2() {
} // <--- 생성자는 private -- 외부에서 new 를 사용하여 객체를 생성할 수 없다...
public static TestThreadClass2 getInstance() { // 객체를 생성하는 static 메소드 하나
if (uniqueInstance == null ) {
synchronized( TestThreadClass2.class ) {
if(uniqueInstance == null ) {
uniqueInstance = new TestThreadClass2();
}
}
}
return uniqueInstance;
}
long threadSafeInt2 = 0;
Member member = new Member();
/**
*
* - 결과 : 로컬 변수는 각 스레드의 stack에 저장하기에 multi thread 환경에서도 safe
* - 참고 : http://tutorials.jenkov.com/java-concurrency/thread-safety.html
*
* @param threadName 스레드 이름
*/
public void testStaticMethod(String threadName) {
System.out.println("threadSafeInt Start : " + threadName);
long threadSafeInt = 0;
threadSafeInt++; // 항상 1 : 로컬 변수의 값은 multiple thread에 safe
System.out.println("threadSafeInt : " + threadSafeInt);
if(threadSafeInt != 1) {
System.out.println("threadSafeInt It is not thread safe : " + threadSafeInt);
}
System.out.println("threadSafeInt End : " + threadName);
}
public void testStaticMethod2(String threadName) {
member.setId("ID : "+String.valueOf(threadSafeInt2));
member.setName("이름 : "+String.valueOf(threadSafeInt2));
System.out.println("testStaticMethod2 Start : " + threadName);
threadSafeInt2++; // 계속 증가 : not thread safe
System.out.println("testStaticMethod2 threadSafeInt : " + threadSafeInt2);
if (threadSafeInt2 != 1) {
System.out.println("testStaticMethod2 It is not thread safe : " + threadSafeInt2);
}
System.out.println("testStaticMethod2 End : " + threadName);
// 결과 : ID 와 Name 이 같은 값으로 나올것 같지만, 실제로는 데이터가 섞임. not thread safe
System.out.println("testStaticMethod2 Member id : " + member.getId()+ " name : "+member.getName());
}
}
댓글