Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- 환경설정
- cursor문
- 어윈 사용법
- 생성자오버로드
- 예외미루기
- GRANT VIEW
- 정수형타입
- exception
- 자동차수리시스템
- 다형성
- 제네릭
- 인터페이스
- 참조형변수
- abstract
- 컬렉션프레임워크
- NestedFor
- oracle
- 오라클
- 컬렉션 타입
- EnhancedFor
- 사용자예외클래스생성
- 자바
- 대덕인재개발원
- 집합_SET
- 메소드오버로딩
- Java
- 객체 비교
- 한국건설관리시스템
- 예외처리
- 추상메서드
Archives
- Today
- Total
거니의 velog
230830_스레드 2 본문
[ConstTest.java]
package kr.or.ddit.basic;
public class ConstTest {
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLUE = 3;
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
}
[EnumTest.java]
package kr.or.ddit.basic;
/*
* enum(열거형) ==> 서로 관련있는 상수들의 집합을 나타낸다.
* ==> 클래스처럼 보이게 하는 상수
*
* - 작성 위치
* 1) 일반 클래스처럼 독립된 java파일로 작성할 수 있다.
* 2) 하나의 java 파일에 클래스와 같이 작성할 수 있다.
* 3) 클래스 안에 내부 클래스처럼 작성할 수 있다.
*
* - 열거형의 속성 및 메서드
* 1) name() ==> 열거형 상수의 이름을 문자열로 반환한다.
* 2) ordinal() ==> 열거형 상수가 정의된 순서값(index값)을 반환한다. (0부터 시작)
* 3) valueOf("상수명") ==> 지정된 열거형에서 '상수명'과 일치하는 열거형 상수를 반환한다.
* 4) 열거형이름.상수명 ==> valueOf() 메서드와 같다.
* 5) 열거형이름.values() ==> 열거형의 모든 상수들을 배열에 담아 반환한다.
*
* - 열거형 선언하기
* 방법1)
* enum 열거형이름 { 상수명1, 상수명2, ..., 상수명n }
*
* 방법2) ==> 열거형 상수에 데이터를 셋팅해서 처리하는 방법
*
* enum 열거형이름 {
* 상수명1(값들...), 상수명2(값들...), ..., 상수명n(값들...);
*
* // '값들'이 저장될 변수들을 선언한다. ('값들'개수에 맞게 변수 선언을 한다.)
* private 자료형이름 변수명1;
* private 자료형이름 변수명2;
* ~~~
*
* // 열거형의 생성자를 만든다.
* // ==> 열거형 생성자는 '열거형 상수에 지정된 값들'을 '변수'에 셋팅하는 역할을 한다.
* // ==> 열거형 생성자는 묵시적으로 접근 제한자가 'private'이다.
*
* // '변수명'은 '값들'과 개수가 같고, 각각의 '값들'과 자료형이 맞아야 한다.
* private 열거형이름(자료형 변수명, ...) {
* 위에서 선언한 변수들을 초기화하는 작업을 한다.
* ...
* }
*
* // 위에서 구성된 '값들'을 외부에서 불러올 수 있는 getter 메서드를 작성한다.
* }
*
*/
public class EnumTest {
// 3) 클래스 안에 내부 클래스처럼 작성할 수 있다.
public enum Color { RED, GREEN, BLUE }
public enum Count { ONE, TWO, THREE }
public enum Season {
// 상수명(값들...) 형식의 선언
봄("3월부터 5월까지", 13), 여름("6월부터 8월까지", 25),
가을("9월부터 11월까지", 15), 겨울("12월부터 2월까지", 1);
// 값들이 저장될 변수 선언
private String span;
private int temp;
// 생성자
Season(String span, int temp) { // private Season(String span, int temp) {} 와 같다.
this.span = span;
this.temp = temp;
}
// getter 메서드 작성
public String getSpan() {
return span;
}
public int getTemp() {
return temp;
}
}
public static void main(String[] args) {
// System.out.println("Red : " + ConstTest.RED); // Red : 1
// System.out.println("Three : " + ConstTest.THREE); // Three : 3
//
// if(ConstTest.RED == ConstTest.TWO) {
// System.out.println("......");
// }else {
// System.out.println("@@@@@@");
// }
// -----------------------------------------------------------
Color myCol = Color.valueOf("GREEN"); // Color.GREEN; 와 같다.
Count myCnt = Count.ONE; // Count.valueOf("ONE"); 와 같다.
System.out.println("myCol : " + myCol.name()); // myCol : GREEN
System.out.println("myCnt : " + myCnt.name()); // myCnt : ONE
System.out.println();
System.out.println("myCol ordinal : " + myCol.ordinal()); // myCol ordinal : 1
System.out.println("myCnt ordinal : " + myCnt.ordinal()); // myCnt ordinal : 0
System.out.println();
// 서로 다른 종류의 열거형 끼리의 비교는 불가능하다. 따라서 상수값으로 직접 비교하는 논리적 오류를 해결할 수 있다.
// if(myCol == myCnt) {
// System.out.println("같다...");
// }
if(myCol == Color.GREEN) { // 같다...
System.out.println("같다...");
}
// 열거형을 switch문에서 사용할 때 case문에는 '열거형이름'을 생략한 '상수명'만 지정해서 비교해야 한다.
switch(myCnt) { // ONE 상수값
case ONE:
System.out.println("ONE 상수값"); break;
case TWO:
System.out.println("TWO 상수값"); break;
case THREE:
System.out.println("THREE 상수값"); break;
}
System.out.println("----------------------------------------");
Season ss = Season.valueOf("봄");
System.out.println("name : " + ss.name()); // name : 봄
System.out.println("ordinal : " + ss.ordinal()); // ordinal : 0
System.out.println("span : " + ss.getSpan()); // span : 3월부터 5월까지
System.out.println("temp : " + ss.getTemp()); // temp : 13
System.out.println();
for(Season time : Season.values()) {
System.out.println(time.name() + " == " + time + " ==> (" + time.getSpan() + ", " + time.getTemp() + ")");
}
System.out.println();
// 봄 == 봄 ==> (3월부터 5월까지, 13)
// 여름 == 여름 ==> (6월부터 8월까지, 25)
// 가을 == 가을 ==> (9월부터 11월까지, 15)
// 겨울 == 겨울 ==> (12월부터 2월까지, 1)
}
}
<스레드>
[1. 프로세스와 쓰레드]
* 프로그램 : 실행 가능한 파일(HDD)
* 프로세스 : 실행 중인 프로그램(메모리)
- 프로세스 : 실행 중인 프로그램, 자원과 쓰레드로 구성
- 쓰레드 : 프로세스 내에서 실제 작업을 수행
모든 프로세스는 하나 이상의 쓰레드를 가지고 있다.
프로세스(공장), 쓰레드(일꾼)으로 비유하면 편하다. |
* 싱글 쓰레드 프로세스 = 자원 + 메서드
* 멀티 쓰레드 프로세스 = 자원 + 쓰레드 + 쓰레드 + ... + 쓰레드
자바에서는 main() 메서드가 하나의 쓰레드이다. 결국은 싱글 쓰레드 프로그램을 짠 것.
멀티프로세스 vs. 멀티쓰레드
- “하나의 새로운 프로세스를 생성하는 것보다 하나의 새로운 쓰레드를 생성하는 것이 더 적은 비용이 든다.
ex) 2프로세스 1쓰레드(공장 2개에 일꾼 1명씩 배치)
ex) 1프로세스 2쓰레드(공장 1개에 일꾼 2명씩 배치)
=> 컴퓨터의 자원을 덜 잡아먹으면서 똑같은 효율을 내는 것이 멀티쓰레드.
“많은 프로그램들이 멀티쓰레드로 작성되어 있다. 그러나, 멀티쓰레드 프로그래밍이 장점만 있는 것은 아니다.”
장점 | 자원을 보다 효율적으로 사용할 수 있다. 사용자에 대한 응답성(responseness)이 향상된다. 작업이 분리되어 코드가 간결해 진다. “여러 모로 좋다” |
단점 | 동기화(synchronization)에 주의해야 한다. => 각각의 스레드가 어떤 자원을 공통으로 사용한다. 즉, 메모리, 변수 등을 공유. 스레드는 동시에 실행되는데, 엄밀히 말하면 동시 실행은 아니다. cpu는 하나인데 뭔가 명령을 처리할 때 처리되는 과정에서 어떤 지점을 멈춰보면 1가지 일 밖에 안 한다. 스레드 실행시 스레드 스케쥴러가 장점 스레드에게 먼저 권한을 줌. 1초의 시간 주면 cpu가 명령어를 읽어서 죽 실행. 1초가 지나면 작업한 지점까지 표시하고 단점 스레드가 실행. 굉장히 짧은 시간동안 여러 개의 명령을 수행하므로 동시에 수행되는 것처럼 보이는 것. 동기화는 예를 들어 장점 스레드가 a 변수값을 사용하다 어떤 값을 나중에 사용하기 위해 a 변수에 값을 저장하고 제어권이 단점으로 넘어감... 단점 스레드도 a 변수값을 공유해서 쓸 수 있으니 자기가 쓰던 데이터를 나중에 쓰기 위해 a 변수에 저장했다고 치자... 그리고 제어가 다시 장점 스레드로 넘어가면? 자기가 저장한 데이터가 아니므로 원하던 결과가 안나올 수 있다. 그래서 장점 스레드는 변수값을 저장하고 보호막을 쳐둠. 단점 스레드가 변수에 저장하려고 보니 저장 안 돼서 보호막이 해제될 때까지 대기. 장점 스레드가 먼저 다 실행되고 보호막 해제. 해제 이후 단점이 다시 변수 사용 가능. 이게 동기화 작업. 교착상태(dead-lock)가 발생하지 않도록 주의해야 한다. 동기화 때문에 일어나는 작업. 장점 스레드가 변수 a에 데이터 넣고 보호막. 프로그램 실행 중 단점 스레드로 제어가 넘어감. 보호막을 해제해야 쓸 수 있는데, 보호막 해제 안 되었는데 장점 스레드가 무엇인가의 오류로 작동을 멈출 수 있다. 단점 스레드 입장에서 a 변수를 써야 하는데, 보호막 해제 못한 상태로 계속 멈춰있는 것처럼 보이는 것. 각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야 한다. 각각의 스케쥴러가 스레드를 관리. 어떤 스레드는 빨리 실행하고, 어떤 스레드는 천천히 실행되도록 관리해야 함. “프로그래밍할 때 고려해야 할 사항들이 많다” |
[2. 쓰레드의 구현과 실행]
1. Thread클래스를 상속
2. Runnable인터페이스를 구현
class MyThread extends Thread { public void run() { 작업내용 } // Thread 클래스의 run()을 오버라이딩 } class MyThread implements Runnable { public void run() { 작업내용 } // Runnable 인터페이스의 추상메서드 run()을 구현 } |
-----------------------------------------------
ThreadEx1_1 t1 = new ThreadEx1_1(); // 객체 생성 후 바로 실행 가능 Runnable r = new ThreadEx1_2(); Thread t2 = new Thread(r); // 생성자 Thread |
[ThreadTest01.java]
package kr.or.ddit.basic;
public class ThreadTest01 {
public static void main(String[] args) {
// '*'문자를 200개 출력하는 기능과 '$'문자를 200개 출력하는 기능 구현하기
// 싱글 쓰레드 프로그램
for(int i=1; i<=200; i++) {
System.out.print("*");
}
System.out.println();
System.out.println();
for(int j=1; j<=200; j++) {
System.out.print("$");
}
System.out.println();
System.out.println();
}
}
[ThreadTest02.java]
package kr.or.ddit.basic;
public class ThreadTest02 {
public static void main(String[] args) {
// 멀티 쓰레드 프로그램
// Thread를 사용하는 방법
/*
* - 방법 1
* 1) Thread 클래스를 상속한 class를 작성한 후 이 class의 인스턴스를 생성한다.
* 2) 이 생성된 인스턴스의 start() 메서드를 호출해서 실행한다.
*/
MyThread1 th1 = new MyThread1(); // 인스턴스 생성
th1.start(); // 쓰레드 실행
// th1.run(); // 싱글 쓰레드처럼 작동한다.
/*
* - 방법 2-1
* 1) Runnable 인터페이스를 구현한 class를 작성한 후 이 class의 인스턴스를 생성한다.
* 2) Thread 클래스의 인스턴스를 생성할 때 Runnable 인터페이스를 구현한 class의
* 인스턴스를 생성자의 인수값으로 넣어준다.
* 3) 생성된 Thread 클래스의 인스턴스의 start()메서드를 호출해서 실행한다.
*/
MyRunner2 r2 = new MyRunner2(); // Runnable 인터페이스를 구현한 클래스의 인스턴스 생성
Thread th2 = new Thread(r2); // Thread의 인스턴스를 생성할 때 Runnable 구현체의 인스턴스를 주입한다.
th2.start(); // 쓰레드 실행
// MyRunner2 eee = new MyRunner2();
/*
* - 방법 2-2 ==> 익명 구현체를 이용하는 방법
*/
Runnable r3 = new Runnable() {
@Override
public void run() {
// '@'문자를 200개 출력하는 기능
for(int k=1; k<=200; k++) {
System.out.print("@");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
};
// --------------------------------------------
Thread th3 = new Thread(r3);
th3.start();
// start() 메서드가 하는 일은 call stack 영역에 main() 메서드 위에 호출되어
// run() 메서드를 개별적인 call stack 메모리로 잡고 사라짐.
// 스레드가 작업할 공간을 만드는 역할을 한다고 보면 된다.
// start() 메서드가 4번 있으면 스레드 작업 공간을 4개 잡고 사라지는 것임.
System.out.println("main() 메서드 끝...");
}
}
// 방법 1
// Thread 클래스를 상속한 class를 작성한다.
class MyThread1 extends Thread {
// run() 메서드를 재정의 한다.
@Override
public void run() {
// 이 run() 메서드 안에는 쓰레드에서 처리할 내용을 작성한다.
// '*'문자를 200개 출력하는 기능
for(int i=1; i<=200; i++) {
System.out.print("*");
try {
// Thread.sleep(시간); ==> 주어진 시간 동안 작업을 잠시 멈춘다.
// '시간'은 millisecond 단위를 사용한다. (즉, 1000은 1초를 의미한다.)
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
}
// 방법 2-1
// Runnable 인터페이스를 구현한 class를 작성한다.
class MyRunner2 implements Runnable {
// run() 메서드를 재정의 한다.
@Override
public void run() {
// 이 run() 메서드 안에는 쓰레드에서 처리할 내용을 작성한다.
// '$'문자를 200개 출력하는 기능
for(int j=1; j<=200; j++) {
System.out.print("$");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
}
[ThreadTest03.java]
package kr.or.ddit.basic;
public class ThreadTest03 {
public static void main(String[] args) {
// 쓰레드가 수행되는 시간을 체크해 보자...
Thread th = new Thread(new MyRunner());
// 1970년 1월 1일 0시 0분 0초(표준시간)로부터 현재까지 경과한 시간을
// millisecond(1/1000초) 단위로 반환한다. ( 예, 3분 경과 ==> 3 * 60 * 1000 )
long startTime = System.currentTimeMillis();
th.start();
try {
th.join(); // 현재 실행 위치에서 대상이 되는 쓰레드(지금은 변수 th)가 종료될 때까지 기다린다.
} catch (InterruptedException e) {
// TODO: handle exception
}
long endTime = System.currentTimeMillis();
System.out.println("경과 시간 : " + (endTime - startTime) + "ms");
}
}
class MyRunner implements Runnable {
@Override
public void run() {
long sum = 0;
for(long i=1L; i<=1_000_000_000L; i++) {
sum += i;
}
System.out.println("합계 : " + sum);
}
}
[ThreadTest04.java]
package kr.or.ddit.basic;
/*
* 1 ~ 20억까지의 합계를 구하는 프로그램을
* 하나의 쓰레드가 단독으로 처리할 때와
* 여러 개의 쓰레드가 협력해서 처리할 때의 경과 시간을 비교해 보자.
*/
public class ThreadTest04 {
public static void main(String[] args) {
// 단독으로 처리하는 쓰레드 객체 생성
SumThread sm = new SumThread(1L, 2_000_000_000L);
// 협력해서 처리할 쓰레드 객체 생성
SumThread[] sumArr = new SumThread[] {
new SumThread( 1L, 500_000_000L),
new SumThread( 500_000_001L, 1_000_000_000L),
new SumThread(1_000_000_001L, 1_500_000_000L),
new SumThread(1_500_000_001L, 2_000_000_000L)
};
// 단독으로 처리하기
long startTime = System.currentTimeMillis();
sm.start();
try {
sm.join();
} catch (InterruptedException e) {
// TODO: handle exception
}
long endTime = System.currentTimeMillis();
System.out.println("단독으로 처리했을 때 경과 시간 : " + (endTime - startTime) + "ms");
System.out.println();
System.out.println("--------------------------------------------------------");
// 협력해서 처리하기
startTime = System.currentTimeMillis();
for(SumThread th : sumArr) {
th.start();
}
for(SumThread th : sumArr) {
try {
th.join();
} catch (InterruptedException e) {
// TODO: handle exception
}
}
endTime = System.currentTimeMillis();
System.out.println("협력해서 처리했을 때 경과 시간 : " + (endTime - startTime) + "ms");
}
}
class SumThread extends Thread {
private long start, end; // 합계를 구할 영역의 시작값과 종료값이 저장될 변수 선언.
// 생성자
public SumThread() {}
public SumThread(long start, long end) {
super();
this.start = start;
this.end = end;
}
@Override
public void run() {
long sum = 0L;
for(long i=start; i<=end; i++) {
sum += i;
}
System.out.println(start + "부터 " + end + "까지의 합계 : " + sum);
}
}
[ThreadTest05.java]
package kr.or.ddit.basic;
import javax.swing.JOptionPane;
public class ThreadTest05 {
public static void main(String[] args) {
// 사용자로부터 데이터 입력 받기
String str = JOptionPane.showInputDialog("아무거나 입력하세요...");
System.out.println("입력한 값 : " + str);
for(int i=10; i>=1; i--) {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
}
[ThreadTest06.java]
package kr.or.ddit.basic;
import javax.swing.JOptionPane;
public class ThreadTest06 {
public static void main(String[] args) {
Thread th1 = new DataInput();
Thread th2 = new CountDown();
th1.start();
th2.start();
}
}
// 데이터를 입력하는 쓰레드 클래스
class DataInput extends Thread {
// 입력 완료 여부를 확인하기 위한 변수 선언 (쓰레드에서 공통으로 사용할 변수)
public static boolean inputCheck = false;
@Override
public void run() {
// 사용자로부터 데이터 입력 받기
String str = JOptionPane.showInputDialog("아무거나 입력하세요...");
inputCheck = true; // 입력이 완료되면 inputCheck 변수를 true로 변경한다.
System.out.println("입력한 값 : " + str);
}
}
// 카운트 다운을 진행하는 쓰레드 클래스
class CountDown extends Thread {
@Override
public void run() {
for(int i=10; i>=1; i--) {
// 입력이 완료되었는지 여부를 검사한다.
// ==> 입력이 완료되면 쓰레드를 종료시킨다.
if(DataInput.inputCheck == true) {
return; // run() 메서드가 종료되면 쓰레드도 종료된다.
}
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
System.out.println("10초가 지났습니다. 프로그램을 종료합니다.");
System.exit(0);
}
}
[ThreadTest07.java]
package kr.or.ddit.basic;
import java.util.HashMap;
import javax.swing.JOptionPane;
/*
* 컴퓨터와 가위 바위 보를 진행하는 프로그램을 작성하시오.
*
* 컴퓨터의 가위 바위 보는 난수를 이용하여 정하고,
* 사용자의 가위 바위 보는 showInputDialog() 메서드를 이용하여 입력 받는다.
*
* 입력 시간은 5초로 제한하고 카운트 다운을 진행한다.
* 5초 안에 입력이 없으면 게임에 진 것으로 처리하고 프로그램을 종료한다.
*
* 5초 안에 입력이 있으면 승패를 구해서 결과를 출력한다.
*
* 결과예시)
* 1) 5초 안에 입력을 못했을 경우
* -- 결 과 --
* 시간 초과로 당신이 졌습니다...
*
* 2) 5초 안에 입력했을 경우
* -- 결 과 --
* 컴퓨터 : 가위
* 당 신 : 바위
* 결 과 : 당신이 이겼습니다.
*
*/
public class ThreadTest07 {
public static void main(String[] args) {
Thread th1 = new UserInput();
Thread th2 = new CountDownMethod();
th1.start();
th2.start();
}
}
class UserInput extends Thread {
// 사용자로부터 데이터 입력 받기
HashMap<Integer, String> dataMap = new HashMap<Integer, String>();
@Override
public void run() {
// 컴퓨터에 랜덤값 넣기
dataMap.put(1, "가위");
dataMap.put(2, "바위");
dataMap.put(3, "보");
int randNum = (int)(Math.random()*3+1);
String randAtk = dataMap.get(randNum);
String str = JOptionPane.showInputDialog("가위 바위 보를 입력하세요.");
// 사용자가 입력하면 입력한 값을 출력, 취소하면 null값 출력
if(str == null) {
System.out.println("게임을 종료합니다.");
System.exit(0);
}
if(!(str.equals("가위") || str.equals("바위") || str.equals("보"))) {
System.out.println("가위, 바위, 보만 입력하세요.");
System.out.println("게임을 종료합니다.");
System.exit(0);
}
CountDownMethod.inputCheck = true;
String result = "";
if(randAtk.equals(str)) {
result = "비겼습니다.";
}else if( (str.equals("가위") && randAtk.equals("보")) || (str.equals("바위") && randAtk.equals("가위")) || (str.equals("보") && randAtk.equals("바위")) ) {
// 모두 사용자가 이긴 경우
result = "당신이 이겼습니다.";
}else {
result = "당신이 졌습니다.";
}
// 결과 출력
System.out.println("-- 결 과 --");
System.out.println("컴퓨터 : " + randAtk);
System.out.println("사용자 : " + str);
System.out.println("결과 : " + result);
System.exit(0);
}
}
class CountDownMethod extends Thread {
public static boolean inputCheck;
@Override
public void run() {
System.out.println("카운트 시작!");
for(int i=5; i>0; i--) {
if(inputCheck == true) {
return;
}
System.out.println(i + "초 남았습니다...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
System.out.println("-- 결 과 --");
System.out.println("시간 초과로 당신이 졌습니다.");
System.exit(0);
}
}
'대덕인재개발원 > 대덕인재개발원_자바기반 애플리케이션' 카테고리의 다른 글
230901_스레드 4 (0) | 2023.09.01 |
---|---|
230831_스레드 3 (0) | 2023.08.31 |
230829_스레드 1 (0) | 2023.08.29 |
230829_컬렉션 프레임워크 6 (1) | 2023.08.29 |
230828_컬렉션 프레임워크 5 (1) | 2023.08.28 |