Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

붓, 그리다

쓰레드 2 (동기화, Singleton) 본문

JAVA/Basic

쓰레드 2 (동기화, Singleton)

붓그린 2017. 6. 19. 12:44
쓰레드에서 주로 사용하는 것
1) 동기화
2) Singleton 패턴




[ 쓰레드 동기화 ]
- 두 쓰레드가 하나의 데이터에 작업을 할 때 한 쓰레드가 진행 중인 작업을 다른 쓰레드가 간섭하지 못하도록 막는 것

RandomAccessFile)

RandomAccessFile raf=null; // 현재폴더 기준 임의의 파일을 생성
 

RandomAccessFile 생성자)

RandomAccessFile(File file, String mode)

- 경로포함해서 생성할 파일명
- 모드: 읽기(r)/읽고 쓰기(rw)



1) 메서드 전체를 임계 영역으로 지정
- 메서드 앞에 synchronized 키워드를 입력

public synchronized void run(){}


EX)

package j0619;
// 동기화
import java.io.*;

// Thread 가동 -> Thread 객체 생성
public class ShareTest implements Runnable { // extends Thread

        RandomAccessFile raf=null; // 현재폴더 기준 임의의 파일을 생성

        // 초기화 작업 -> 생성자 : Thread 객체를 생성하여 한개의 파일에 데이터를 입력하도록 처리
        public ShareTest() {
                try {
                        raf=new RandomAccessFile("c:/3.java/result.txt","rw");
                        //Thread 객체 생성
                        Thread t1=new Thread(this,"lgw"); //인수 2개: Runnable 객체명, 쓰레드 이름 부여
                        // 쓰레드 이름을 부여하지 않으면 setName() 사용
                        Thread t2=new Thread(this,"test");
                        t1.start(); t2.start();
                }catch(IOException e) {
                        System.out.println("파일생성에 오류"+e); // e.toString();
                }
        }

        @Override
                public synchronized void run() {//Thread 기능 : 파일에 내용을 써주는 기능
                        // TODO Auto-generated method stub
                        // raf의 writeBytes()를 이용, FilePointer() : 글짜를 쓸때마다 포인터 이동
                        try {
                                for(int i=0;i<1000;i++) {
                                        raf.writeBytes(Thread.currentThread().getName()+"["+i+"]"+raf.getFilePointer()+"\n");
                                }
                        }catch(Exception e) {
                                System.out.println("파일의 출력오류"+e);
                        }
                }

        public static void main(String[] args) {
                // TODO Auto-generated method stub
                // 1) ShareTest 객체생성
                new ShareTest();
        }

}

-> 둘 중 하나가 먼저 저장



2) 특정한 영역을 임계 영역으로 지정
- 메서드 내부에 synchronized 예약어를 이용해서 특정 공유 객체를 설정
- 하나의 쓰레드가 사용되며 다른 쓰레드는 대기

package j0619;

//급여통장(공유객체) -> ATM(Thread 작동)
class ATM implements Runnable{

        //급여계좌 금액
        private long Money=10000;


        @Override
        public void run() {
                // TODO Auto-generated method stub
                // 형식) synchronized(공유객체명){처리할 문장;}
                synchronized(this) { //자기 클래스에선 자기 객체명을 쓸 수 없다.
                        for(int i=0;i<5;i++) {
                                try {
                                        Thread.sleep(1000); //1초간격으로 실행
                                }catch(Exception e){}
                                if(getMoney()<=0)
                                        break;
                                withDraw(1000);
                        }//for
                } //synchronized
        }

        // 돈을 인출시켜주는 메서드 => 수정목적
        public void withDraw(long howmuch) {
                if(getMoney()>0) {// if(Money > ) = if(this.getMoney()>-)
                        Money-=howmuch;
                        System.out.println(Thread.currentThread().getName()+", "+getMoney());
                } else {
                        System.out.println("잔액이 부족합니다.");
                }
        }

        // 잔액조회 -> getter
        public long getMoney() {
                return Money;
        }


}

public class SyncTest {

        public static void main(String[] args) {
                // TODO Auto-generated method stub
                ATM atm=new ATM();
                Thread t1=new Thread(atm,"보험금");
                Thread t2=new Thread(atm,"공과금");
                t1.start(); t2.start();
        }

}






[ Singleton 패턴 ]
- 동기화처리하기 때문


package j0619;
// 클래스 내부에서 특정객체를 한개만 생성하여 대여 반납하기
public class Singleton {

        // 1) 객체를 하나만 생성
        // 형식) private static 클래스명 객체명 = null;
        private static Singleton instance=null; //멤버변수를 정적으로 선언


        // 2) 객체를 생성 -> 생성자 호출
        // 형식) private 생성자(){}
        private Singleton() {
                System.out.println("인스턱스(객체) 생성");
        }


        // 3) 공유객체를 다른 사람들에게 공유 => 정적메서드
        // 형식) public static 클래스의 자료형 정적메서드명() 선언해서 작성
        public static Singleton getInstance() {
                 if(instance==null) { // 아직 메모리에 없는 상태라면
                         // 만들고자 하는 객체를 공유객체로 등록 -> synchronized
                         synchronized(Singleton.class) {
                                 if(instance==null) {
                                         instance=new Singleton();
                                 }
                         }
                 }//if
                 return instance;
        }
}



package j0619;

public class Main {

        public static void main(String[] args) {
                // TODO Auto-generated method stub
                //외부에서 접근이 불가 => 생성자 호출이 안되기 때문에 객체생성이 안됨
                // Singleton ob1=new Singleton();
                // 정적메서드를 이용하여 객체를 대여
                Singleton ob1=Singleton.getInstance();
                Singleton ob2=Singleton.getInstance();
                Singleton ob3=Singleton.getInstance();

                System.out.println("ob1=>"+ob1);
                System.out.println("ob2=>"+ob2);
                System.out.println("ob3=>"+ob3);
                if(ob1==ob2) // 주소값을 비교하여 주소가 같고 일반변수라면 내용을 비교
                        System.out.println("ob1=ob2");
                else
                        System.out.println("ob1!=ob2");
        }

}





'JAVA > Basic' 카테고리의 다른 글

제너릭 Genrics 개요  (0) 2017.06.20
컬렉션 ★★  (0) 2017.06.19
상속, 오버라이딩  (0) 2017.06.16
쓰레드  (0) 2017.06.16
입출력(직렬화)  (0) 2017.06.16
Comments