stop 메소드 대신
package kr.or.ddit.basic;
/*
* Thread 의 stop() 메소드를 호출하면 쓰레드가 바로 멈춘다.
* 이때 사용하던 자원을 정리하지 못하고 프로그램이 종료되어
* 나중에 실행되는프로그램에 영향을 줄 수 있다.
* 그래서 stop () 메서드는 비추천으로 되어 있다.
*
*
*
*/
public class ThreadTest14 {
public static void main(String[] args) {
/*
ThreadStopTest1 th1 = new ThreadStopTest1();
th1.start();
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
// th1.stop();
th1.setStop(true);
*/
//interrupt() 메서드를 이용한 쓰레드 멈추기
ThreadStopTest2 th2 = new ThreadStopTest2();
th2.start();
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
th2.interrupt();
}
}
// 쓰레드를 멈추게 하는 연습용 쓰레드
class ThreadStopTest1 extends Thread {
private boolean stop; // 쓰레드를 멈추게 하는 제어용 변수 선언.
public void setStop(boolean stop) {
this.stop = stop;
}
@Override
public void run() {
while (!stop) {
System.out.println("쓰레드 실행중....");
}
System.out.println("자원 정리...");
System.out.println("쓰레드 종료");
}
}
// interrupt() 메서드를 이용하여 쓰레드를 멈추게 하는 방법
//
class ThreadStopTest2 extends Thread {
@Override
public void run() {
/*
//1) interrupt() 메서드와 sleep()메서드를 이용하는 방법
// 쓰레드가 일시정지한 상태에서 interrupt() 메서드가 호출되면
// 해당 쓰레드는 일시정지 상태에서 풀려나고 동시에 InterruptedException 을 발생시킨다.
try {
while (true) {
System.out.println("실행중");
Thread.sleep(1);
}
} catch (InterruptedException e) {
}
*/
//방법 2)
while(true) {
System.out.println("Thread 실행중..");
//interrupt() 메서드가 호출되었는지 검사한다.
/*// 검사방법 1) 쓰레드의 인스턴스 메서드인 isInterrupted() 메서드를 이용한다.
// isInterrupted() 메서드는 interrupt() 메서드가 호출되면
// isInterrupted() 메서드는 interrupt() 메서드가 호출되면 true 를 반환한다.
if(this.isInterrupted()) {
break;
}
}*/
// 검사방법 2) 쓰레드의 정적메서드인 interrupted() 메서드 이용하기
// interrupted() 메서드 ==> interrupt() 메서드가 호출되면 true 를 반환한다.
if(Thread.interrupted()) {
break;
}
}
System.out.println("자원정리...............");
System.out.println("쓰레드종료...............");
}
}
-----------------------------------------------------------------------------------------------------
여러쓰레드가 같은 데이터를 공유
package kr.or.ddit.basic;
//쓰레드에서 객체를 공통으로 사용하는 예제
/*
* 원주율을 계산하는 쓰레드와
* 계산된 원주율을 출력하는 쓰레드
*
*
* 원주율을 저장하는 객체가 필요하다.
* 이 객체를 두 쓰레드에서 공통으로 사용해서 처리한다.
*
*
*/
public class ThreadTest15 {
public static void main(String[] args) {
// 공통으로 사용할 객체를 먼저 생성
ShareData sd = new ShareData();
//쓰레드 객체를 생성한다. 공통으로 사용할 객체를 쓰레드에 주입한다.
PrintPIThread printPi = new PrintPIThread(sd);
CalcPIThread calcPi = new CalcPIThread();
calcPi.setSd(sd);
System.out.println("계산 시작 ");
calcPi.start();
printPi.start();
}
}
//원주율을 계산하는 쓰레드
class CalcPIThread extends Thread {
private ShareData sd;
/*생성자
* public CalcPIThread( ShareData sd) {
this.sd = sd;
}*/
//생성자를 안만드려면 이렇게 하면 된다.
public void setSd(ShareData sd) {
this.sd = sd;
}
//
@Override
public void run() {
/*
*
* 원주율 = (1/1 - 1/3 + 1/5 - 1/7 + 1/9 - ...... ) * 4 ;
*
* 1, - 3, 5, - 7, 9
* 0 1 2 3 4
* 2로 나눈것의 홀수 : -
* 2로 나눈것의 짝수 : +
*
*
*
*
*/
double sum = 0.0 ;
for(int i = 1 ; i <= 2000000000 ; i+=2) {
if ((i/2) % 2 == 0 ) {
sum += 1.0/i;
}else {
sum -= 1.0/i;
}
sd.result = sum * 4 ;
sd.isOk = true; // 메모리에 있는 데이터를 가져와다가 바꿨어.
}
}
}
//원주율을 출력하는 쓰레드
class PrintPIThread extends Thread {
private ShareData sd; // 공통으로 사용할 객체의 참조값이 저장될 변수 선언
public PrintPIThread(ShareData sd) {
this.sd = sd;
}
@Override
public void run() {
while(true) {
if(sd.isOk) { //계산이 완료되었는지 검사
break; //캐시에다가 가져다 놓고 캐시에서 비교를 한다...
//다른 쓰레드가 변경을 해줬는데도 캐시에서가져온 데이터만 비교하기 때문에 결과가 안나올 수 있다.
// valotile 을 붙이면 -> 무조건 메모리에서 읽어와라라는 뜻.
}
}
System.out.println("결과 : " + sd.result);
System.out.println("PI : " + Math.PI);
}
}
//공통으로 사용할 클래스 ==> 원주율을 관리하는 클래스
class ShareData {
public double result; //계산된 원주율이 저장될 변수
//volatile ==> cpu 하고의 속도 차이 줄이기 위해 램 (메모리 ) 에서데이터를 캐시에 저장을 해놓고 cpu 가
//사용을 한다.
// 캐시 : 서버에 있는 데이터와 화면에 있는 데이터중에 변경된거만 보여준다. ( 내컴퓨터에서 읽어서 보여줌)
public volatile boolean isOk ; //계산이 완료되었는지 여부를 나타내는 변수
//volatile : 이 키워드가 붙은 변수는 컴파일러의 최적화 대상에서 제외된다.
// 캐쉬에서 가져와서 비교하는 것이 아니라 메모리에서 비교해라 라는 뜻.
// 즉, 값이 변경되는 즉시 변수에 적용시킨다.
}
-----------------------------------------------------------------------------------------------------
제어가 어디에 있냐에 따라 출력되는 데이터가 다르다
package kr.or.ddit.basic;
public class ThreadTest16 {
public static void main(String[] args) {
ShareObject sObj = new ShareObject();
TestThread th1 = new TestThread("1번쓰레드" , sObj);
TestThread th2 = new TestThread("2번쓰레드" , sObj);
th1.start();
th2.start();
}
}
class TestThread extends Thread {
private ShareObject sObj ;
//생성자
public TestThread(String name, ShareObject sObj) {
super(name); // 쓰레드의 name을 설정한다.
this.sObj = sObj;
}
@Override
public void run() {
for ( int i = 0 ; i < 10 ; i++) {
sObj.add();
}
}
}
//공통으로 사용할 클래스
class ShareObject {
private int sum = 0 ;
public void add() {
int n = sum ;
n += 10 ;
sum = n;
System.out.println(Thread.currentThread().getName() + "합계 :" + sum);
// 제어가 어떤시점에 어디 쓰레드로 변경했는지에 따라서 데이터가 이상하게 나올수 있다. 결과는 200으로 나오지만
}
}
-----------------------------------------------------------------------------------------------------
동기화
package kr.or.ddit.basic;
//은행의 입출금을 쓰레드로 처리하는 예제
//(동기화 처리 예제)
public class ThreadTest17 {
private int balance; //잔액이 저장될 변수
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
//입금하는 메서드
public void deposit (int money) {
balance += money ;
}
// 출금하는 메서드 출금성공 : true , 출금 실패 : false 를 반환
public /*synchronized */boolean withdraw(int money) { // 첫번쨰는 동기화 메소드
synchronized(this) { //동기화 블럭
if(balance >= money) {
for(int i = 1 ; i <= 100000000 ; i++ ) {} // 시간 지연용
balance -= money;
System.out.println("메서드 안에서 balance : " + getBalance());
return true;
}else {
return false;
}
}
}
public static void main(String[] args) {
ThreadTest17 acount = new ThreadTest17();
acount.setBalance(10000); // 잔액을 10000원이라고 설정 .
//익명 구현체로 쓰레드 구현
Runnable test = new Runnable() {
@Override
public void run() {
boolean result = acount.withdraw(6000); // 6000원 출금하기
System.out.println("쓰레드에서 result 는 : " + result + ", balance : " + acount.getBalance());
}
};
//------------------------------------------------------------------------//익명구현체
Thread th1 = new Thread(test);
Thread th2 = new Thread(test);
th1.start();
th2.start();
}
}
댓글
댓글 쓰기