Java Singleton Type Class

2023. 3. 30. 23:37Java

프로젝트 내 src 내 javabasic 패키지 내 SingleTonEx1.java

package javabasic;

public class SingleTonEx1 {// 인스턴스를 하나만 생성하고, 더이상 생성못함
	private static SingleTonEx1 instance = new SingleTonEx1();

	// 인스턴스를 하나만 생성하도록하는 싱글톤타입으로 클래스를 만드려면 생성자를
	// private으로 외부에서 접근못하게 해야 한다 클래스생성자를 private으로설정
	// static 키워드는 클래스를 로딩할 때 컴파일타임에 이미 만들어져버리기 때문에
	// 실행중에 어떤 다른 처리가 필요하다면 불편하다
	private SingleTonEx1() {
	}

	public static SingleTonEx1 getInstance() {
		return instance;
	}
}

프로젝트 내 src 내 javabasic 패키지 내 SingleTonEx2.java

package javabasic;

import java.util.Random;

public class SingleTonEx2 {
	private static SingleTonEx2 instance = null;

	private int randomNumber;

	// 생성자를 private 이면 요 클래스 내에서만 생성할 수 있다는 것
	private SingleTonEx2() {
	}

	// getInstance() 메소드를 호출하지 않는다면 아예 이클래스의 인스턴스는 생성안된다
	// 한번도 생성되지않는 그런 패턴이 될수있다
	public static SingleTonEx2 getInstance() {
		if (instance == null) {
			instance = new SingleTonEx2();
			// SingleTonEx1은 클래스가 static이라 시작하자마자 바로 인스턴스가 생성되었지만 아예 객체가 미리 만들어져버리지만
			// 요 SingleTonEx2는 getInstance()를 실행했을 때 동시에 바로 어떤 새로운 다른 처리를 할 수 있다.
			Random rand = new Random();
			// static 메소드에서는 non-static 변수를 못쓰므로
			// instance의 randomNumber 자기자신의자식멤버로 접근한다
			instance.randomNumber = rand.nextInt(5) + 1;
		}

		return instance;
	}

	public int getRandomNumber() {
		return randomNumber;
	}
}

프로젝트 내 src 내 javabasic 패키지 내 SingleTonEx3.java

package javabasic;

import java.util.Random;

public class SingleTonEx3 {
	private static SingleTonEx3 instance = null;

	private int randomNumber;

	// 생성자를 private 이면 요 클래스 내에서만 생성할 수 있다는 것
	private SingleTonEx3() {
	}
	// getInstance() 메소드를 호출하지 않는다면 아예 이클래스의 인스턴스는 생성안된다
	// 한번도 생성되지않는 그런 패턴이 될수있다

	// 객체를 두사람이 동시에 만들려고 이 클래스의 인스턴스를 동시에 만들면
	// 객체가 2개 생길 문제가 있다. 그럴때 동기화 synchronized 를 쓴다
	// 동시에 이 영역을 침범하지 못한다. 다른 프로그램은 먼저 또다른 프로그램이
	// 이 영역을 쓰고 나서 요 자원을 쓴다. 두번째 예제를 해결...두번째예제는 첫예제를 해결
	public static synchronized SingleTonEx3 getInstance() {
		if (instance == null) {
			instance = new SingleTonEx3();
			// SingleTonEx1은 클래스가 static이라 시작하자마자 바로 인스턴스가 생성되었지만 아예 객체가 미리 만들어져버리지만
			// 요 SingleTonEx2는 getInstance()를 실행했을 때 동시에 바로 어떤 새로운 다른 처리를 할 수 있다.
			Random rand = new Random();
			// static 메소드에서는 non-static 변수를 못쓰므로
			// instance의 randomNumber 자기자신의자식멤버로 접근한다
			instance.randomNumber = rand.nextInt(5) + 1;
		}

		return instance;
	}

	public int getRandomNumber() {
		return randomNumber;
	}
}

프로젝트 내 src 내 javabasic 패키지 내 SingleTonEx4.java

package javabasic;

import java.util.Random;

public class SingleTonEx4 {
	private static SingleTonEx4 instance = null;

	private int randomNumber;

	// 생성자를 private 이면 요 클래스 내에서만 생성할 수 있다는 것
	private SingleTonEx4() {
	}
	// getInstance() 메소드를 호출하지 않는다면 아예 이클래스의 인스턴스는 생성안된다
	// 한번도 생성되지않는 그런 패턴이 될수있다

	// 객체를 두사람이 동시에 만들려고 이 클래스의 인스턴스를 동시에 만들면
	// 객체가 2개 생길 문제가 있다. 그럴때 동기화 synchronized 를 쓴다
	// 동시에 이 영역을 침범하지 못한다. 다른 프로그램은 먼저 또다른 프로그램이
	// 이 영역을 쓰고 나서 요 자원을 쓴다. 두번째 예제를 해결...두번째예제는 첫예제를 해결
	// 이번에는 인스턴스화 하기 전의 작업.고작업만 동기화를 시켜줄것이다
	// 함수전체에다 동기화걸지않고 생성직전에 영역만 잡아줄수있다.효율.
	// 싱크로나이즈드 동기화 이용하면 여러가지 효율적면에서 좀 떨어지는 면이 있다
	// 동시접근이 안되니깐 프로세스 처리가 길다고 가정하면 계속기다려야 하는 불편암이
	// 있다.그래서 밑에 처럼 인스턴스화 하기 전의 생성 직전의 영역만 잡는다. 함수전체
	// 보다는 좀더 효율적인 작업을 할 수 있다.
	public static SingleTonEx4 getInstance() {
		synchronized (SingleTonEx4.class) {
			if (instance == null) {
				instance = new SingleTonEx4();
				// SingleTonEx1은 클래스가 static이라 시작하자마자 바로 인스턴스가 생성되었지만 아예 객체가 미리 만들어져버리지만
				// 요 SingleTonEx2는 getInstance()를 실행했을 때 동시에 바로 어떤 새로운 다른 처리를 할 수 있다.
				Random rand = new Random();
				// static 메소드에서는 non-static 변수를 못쓰므로
				// instance의 randomNumber 자기자신의자식멤버로 접근한다
				instance.randomNumber = rand.nextInt(5) + 1;
			}
		}

		return instance;
	}

	public int getRandomNumber() {
		return randomNumber;
	}
}

프로젝트 내 src 내 javabasic 패키지 내 SingleTonTest.java

package javabasic;

public class SingleTonTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("------------시작------------");
		// 싱글톤 객체를 만들어야 하는데 우리는 싱클톤객체를 생성하지 못하고
		// 반환만 받을수있다.
		SingleTonEx1 singleton1 = SingleTonEx1.getInstance();
		SingleTonEx1 singleton2 = SingleTonEx1.getInstance();

		if (singleton1 == singleton2) {
			System.out.println("서로 같은 객체입니다...");
		} else {
			System.out.println("서로 다른 객체입니다....");
			System.out.println("-------------end-------------");
		}

//		SingleTonEx2 singleton3 = SingleTonEx2.getInstance();
//		SingleTonEx2 singleton4 = SingleTonEx2.getInstance();
//		
//		if(singleton3 == singleton4) {
//			System.out.println("서로 같은 객체입니다...");
//		}else {
//			System.out.println("서로 다른 객체입니다....");
//			System.out.println("-------------end-------------");
//		}
//		
//		System.out.printf("singleton3 : %d, singleton4 : %d\n", singleton3.getRandomNumber(), singleton4.getRandomNumber());

		ThreadSt threadSt1 = new ThreadSt();
		ThreadSt threadSt2 = new ThreadSt();
		Thread thread1 = new Thread(threadSt1, "1");
		Thread thread2 = new Thread(threadSt2, "2");

		thread1.start();
		thread2.start();

//		System.out.println("-----SingleTonEx2 를 여러 사람이 동시에 만든다.-----");
//		
//		ThreadStEx2 threadStEx2_1 = new ThreadStEx2();
//		ThreadStEx2 threadStEx2_2 = new ThreadStEx2();
//		Thread thread3 = new Thread(threadStEx2_1, "3");
//		Thread thread4 = new Thread(threadStEx2_2, "4");
//		
//		thread3.start();
//		thread4.start();
	}

}

class ThreadSt implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis();

		for (int i = 0; i < 6; i = i + 1) {

//			System.out.println("SingleTonEx2 : " + SingleTonEx2.getInstance().getRandomNumber());
//			System.out.println("SingleTonEx3 : " + SingleTonEx3.getInstance().getRandomNumber());
//			System.out.println("SingleTonEx4 : " + SingleTonEx4.getInstance().getRandomNumber());
			// 위와 같이 SingleTonEx2, SingleTonEx3, SingleTonEx4 세 개를
			// for 반복문에서 함께 돌리면 확률적으로 SingleTonEx2 객체에서 무작위수가
			// 다른 값이 나올 경우가 낮아지기 때문에 SingleTonEx2 와 SingleTonEx3
			// 두 개만 돌린다. 그러면 확률적으로 겹치지 않는 값이 나오고,
			// SingleTonEx2 를 동시에 두 스레드가 run() 함수를 돌릴 때
			// 싱글톤 패턴이 아닌 객체가 2개가 생기는 경우가 잘 나오게 된다.
			// 위와 같이 생각하고 나서 아래와 같이 SingleTonEx2 와 SingleTonEx3
			// 만 출력하도록 하였지만 SingleTonEx2, SingleTonEx3,
			// SingleTonEx4 세 가지 다 출력하였을 때와 차이 없이 다른 값이 잘
			// 나오지 않았다.그냥 계속 빠르게 연속적으로 Java Application 을
			// 실행하지 않고 시간여유를 두면서 실행하거나 Remove All Terminated
			// Launches 라는 Eclipse IDE 하단에 콘솔창에 콘솔탭 옆에 엑스2개표시를
			// 누르고 다시 실행하다보면 어쩌다가 SingleTonEx2 객체 2개가 생기면서
			// 랜덤값이 다르게
			// 배정되어 나온다.

			System.out.println("SingleTonEx2 : " + SingleTonEx2.getInstance().getRandomNumber());
			System.out.println("SingleTonEx3 : " + SingleTonEx3.getInstance().getRandomNumber());

			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		long end = System.currentTimeMillis();
		System.out.println("실행 시간 : " + (end - start) / 1000.0);
		// SingleTonEx3 와 SingleTonEx4 에서 동기화를 걸어주는 위치에 따라서
		// 실행속도가 달라진다는 가정하에 시간을 재어보았지만 별 차이가 나지 않는다.
		// 동기화를 걸어주는 함수 내에 프로세스 처리가 길어야 하는데 그렇지 않아서 그런 듯 하다..
	}

}

class ThreadStEx2 implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 2; i++) {
			System.out.println(SingleTonEx2.getInstance().getRandomNumber());
		}

		try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

실행 결과

------------시작------------
서로 같은 객체입니다...
SingleTonEx2 : 0
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx3 : 3
SingleTonEx2 : 4
SingleTonEx3 : 3
실행 시간 : 1.275
실행 시간 : 1.275

프로젝트 내 src 내 javabasic 패키지 내 SingleTonTest2.java

package javabasic;

public class SingleTonTest2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("------------시작------------");
		// 싱글톤 객체를 만들어야 하는데 우리는 싱클톤객체를 생성하지 못하고
		// 반환만 받을수있다.
		SingleTonEx1 singleton1 = SingleTonEx1.getInstance();
		SingleTonEx1 singleton2 = SingleTonEx1.getInstance();

		if (singleton1 == singleton2) {
			System.out.println("서로 같은 객체입니다...");
		} else {
			System.out.println("서로 다른 객체입니다....");
			System.out.println("-------------end-------------");
		}

		ThreadSt2 threadSt1 = new ThreadSt2();
		ThreadSt2 threadSt2 = new ThreadSt2();
		Thread thread1 = new Thread(threadSt1, "1");
		Thread thread2 = new Thread(threadSt2, "2");

		thread1.start();
		thread2.start();

	}

}

class ThreadSt2 implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis();

		for (int i = 0; i < 6; i = i + 1) {

			System.out.println("SingleTonEx2 : " + SingleTonEx2.getInstance().getRandomNumber());
			System.out.println("SingleTonEx4 : " + SingleTonEx4.getInstance().getRandomNumber());

			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		long end = System.currentTimeMillis();
		System.out.println("실행 시간 : " + (end - start) / 1000.0);
	}

}

실행 결과

------------시작------------
서로 같은 객체입니다...
SingleTonEx2 : 0
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx2 : 5
SingleTonEx2 : 5
SingleTonEx4 : 5
SingleTonEx4 : 5
실행 시간 : 1.272
실행 시간 : 1.273

 

'Java' 카테고리의 다른 글

Java getActionCommand()  (0) 2023.04.06
Java ResultSetMetaData  (0) 2023.04.04
Java afterLast()  (0) 2023.03.28
Java JDBC™ 4.2 API  (0) 2023.02.28
Java - java.sql  (0) 2023.02.27