붓, 그리다
쓰레드 2 (동기화, Singleton) 본문
쓰레드에서 주로 사용하는 것
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");
}
}
Comments