Properties
- Key 와 Value를 쌍으로 저장하는 자료구조
- Map 은 모든 자료형을 사용할 수 있지만 Properties는 Key 와 Value 모두 String 만 가능
- 자료형이 결정되어 있어서 앞에 나온 자료구조 들과 다르게 Generics을 이용하지 않습니다.
- 환경설정을 xml 이나 텍스트 파일에 작성해두고 그 내용을 읽어서 프로그램에 적용하고자 하는 용도로 많이 사용
- Spring 같은 프레임워크에서는 메시지 출력 등에 이용됩니다.
1.주요 메소드
String setProperty(String key, String value)
: 프로퍼티 저장String getProperty(String key)
: key에 해당하는 프로퍼티를 가져옵니다.void store(OutputStream stream, String comment)
: comment 와 함께 stream(파일이나 네트워크)에 내용을 저장void storeToXML(OutputStream stream, String comment)
: comment 와 함께 stream에 XML 형식으로 저장
2.XML(eXtensible Markup Language): 태그 형식으로 표현하는데 해석을 브라우저가 하지 않고 개발자나 설정된 스키마가 해석하는 형식의 문서
- 이전에 web에서 데이터를 전송하기 위한 표준으로 사용되었고 설정 파일에 많이 이용되었습니다.
- HTML(View)은 비구조적이기고 느슨한 문법을 적용하지만 XML(Data)은 구조적이고 엄격한 문법을 제공
3.현재 작업디렉토리 사용
./
: 현재 작업 디렉토리, 생략하고 파일 경로만 적으면 현재 작업디렉토리에서 작업을 합니다.- 명령어를 입력할 때는 Mac에서는 ./를 생략하면 명령어가 없다고 나옵니다.
4.실습 - 프로퍼티를 만들고 저장하기: 프로젝트 디렉토리에서 파일 생성여부 확인
public static void main(String[] args) {
//프로퍼티를 저장할 수 있는 인스턴스를 생성하고 데이터를 저장
Properties props = new Properties();
//프로퍼티 저장
props.setProperty("name", "베르캄프");
props.setProperty("nation", "holland");
//프러퍼티 나 맵(dictionary, hashtable 라고도 합니다.)
//프로퍼티나 맵에 없는 key의 값을 주었을 때 동작 방식
String name = props.getProperty("name");
//자바는 없는 key를 사용하면 null
String age = props.getProperty("age");
System.out.println(name);
System.out.println(age);
//props를 현재 디렉토리에 temp.xml 파일로 내보내기
try {
props.storeToXML(new FileOutputStream("temp.xml"), "주석");
}catch(Exception e) {
System.out.println("예외발생:" + e.getMessage());
}
}
Collections 클래스
- 자바의 자료구조들을 동기화 된 자료구조 와 변경 불가능한 자료구조로 변환해주는 클래스로 모든 메소드가 static으로 만들어져 있어서 인스턴스를 생성할 필요가 없고 모든 메소드가 매개변수를 대입된 데이터를 변경하지 않고 리턴을 합니다.
- synchronized 가 붙으면 동기화 된 자료구조를 만들어주는 메소드
- 동기화: 읽기를 하는데는 아무런 제한이 없지만 수정이나 삽입 및 삭제등의 작업을 할 때는 다른 스레드가 사용 중이면 작업이 종료될 때 까지 기다렸다가 수행
//동기화가 적용되지 않은 List
List <String> list = new ArrayList<String>();
List<String>syncList = Collections.synchronizedCollection(list);
//syncList는 동기화가 적용된 List
- unmodifiable이 붙으면 변경이 불가능한 자료구조를 생성
final List <String> list = new ArrayList<String>();
//final이 붙은 경우는 list를 수정하지 못하는 것이지 list 안의 데이터를 수정 못하는 것이 아닙니다.
list = new ArrayList<String>(); //이 구문은 에러 list 자체를 변경할려고 해서 에러
list.add("Hello World"); //이 구문은 에러가 아님, list 내부를 수정하는 것은 가능
List <String> imList = Collections.unmodifiableCollection(list);
//imList는 내부 데이터를 수정하지 못합니다.
- checked를 추가하면 1가지 데이터 타입만 사용이 가능
- 이 부분은 제너릭을 적용하면 동일한 효과를 만들 수 있음
- 제너릭을 적용하지 않고 만들어진 자료구조라면 이 메소드를 이용해서 제너릭을 적용하는 효과를 만들 수 있습니다.
- 제너릭은 인스턴스를 만들 때 자료형을 결정하는 것으로 자료구조 클래스에서 주로 이용
List <String> list = new ArrayList<String>(); //list에는 String 만 저장 가능
List list1 = new ArrayList(); //list1에는 모든 자료형의 데이터를 저장할 수 있습니다.
- 자동으로 Object 의 List가 됩니다.
- 이런 경우 String 만 저장하도록 변경하고자 하는 경우에 checked를 사용
List list2 = Collections.checkedCollection(list1, String.class);
- list2는 String 만 저장 가능
java.util.Random
- 랜덤한 값을 생성해주기 위한 클래스
- 랜덤한 값은 seed(난수표)에서 데이터를 순서대로 하나씩 가져오는 개념
- seed가 고정이 되면 랜덤 값은 일정한 패턴으로 리턴됩니다.
1.생성자
- Random(): 현재 시간을 기준으로 해서 seed를 설정, 생성될 때 마다 seed 가 변경될 가능성이 높음
- Random(long seed): seed를 매개변수로 설정
2.메소드
float nextFloat()
: 실수형 난수 생성해서 리턴int nextInt
: 정수형 난수 생성int nextInt(int n)
: %n 한 결과의 난수를 생성void setSeed(long seed)
: seed를 변경
3.java.util.UUID 클래스
- 이 클래스의 static 메소드인 randomUUID()를 호출하면 랜덤한 문자열을 생성
- 결과를 toString()으로 확인하면 랜덤한 문자열을 확인할 수 있습니다.
4.랜덤 실습1
public static void main(String[] args) {
//seed 설정 없이 랜덤 인스턴스 생성 - seed 가 현재 시간을 설정
Random r1 = new Random();
//seed를 1번으로 설정
Random r2 = new Random(1);
//실행할 때 마다 다르게 나옴
int result1 = r1.nextInt();
//실행할 때 마다 동일하게 나옴
int result2 = r2.nextInt();
System.out.println("result1:" + result1);
System.out.println("result2:" + result2);
//빨강, 파랑, 녹색 을 랜덤하게 출력
//랜덤하게 출력되는 것에 제한을 가하기 위한 배열을 생성
String [] colors = {"머니", "머니", "아이템1", "아이템2", "아이템3"};
//배열에서 배열안의 인덱스가 랜덤하게 나오도록 r1.nextInt(colors.length)
//배열의 인덱스에 적용
for(int i=0; i<10; i=i+1) {
String color = colors[r1.nextInt(colors.length)];
System.out.println("color:" + color);
}
//비복원 추출 - 훈련데이터 와 테스트데이터 샘플링, 로또, 고스톱, 포커
List<String> list = new ArrayList<String>();
//1-45까지 저장
for(int i=1; i<=45; i=i+1) {
list.add(i + "");
}
//20개의 숫자를 비복원 추출
for(int i=0; i<20; i=i+1) {
//list 사이즈 내에서 데이터를 추출
String x = list.get(r1.nextInt(list.size()));
//그 데이터를 제거
list.remove(x);
System.out.print(x + "\t");
}
}
5.랜덤 실습2
public static void main(String[] args) {
String [] image = {"!", "@", "#", "$", "%", "^"};
//Random 객체 생성
Random r = new Random();
List<String> list = new ArrayList<String>();
for(int i=0; i<3; i=i+1) {
String temp = image[r.nextInt(image.length)];
System.out.print(temp);
list.add(temp);
}
System.out.print("\n");
if(list.get(0) == list.get(1) && list.get(1) == list.get(2)) {
System.out.println("3개가 모두 일치");
}else if(list.get(0) == list.get(1)) {
System.out.println("앞의 2개가 일치");
}else {
System.out.println("꽝");
}
//랜덤한 문자열 만들기 - 이미지 파일 등을 업로드 했을 때 파일이름 그리고 유저를 구분하기 위한 이름
//등을 만들 때 이용
String name = UUID.randomUUID().toString();
System.out.println(name);
}
날짜 관련 클래스
1.java.util.Date 클래스
- 날짜와 시간을 저장하기 위한 클래스
1) 생성자
Date()
: 현재 날짜 및 시간을 가지고 생성Date(long timeMillis)
: 1970년1월1일 자정 이후부터 지나온 시간을 밀리초 단위로 입력해서 생성Date(int year, int month, int day)
: 년월일을 입력해서 생성, 년도는 1900년 이후에 지나온 시간, 월은 0부터 시작하기 때문에 하나 적게 설정, day는 일반적인 형태로 설정2020년 1월 17일 : new Date(120, 0, 17)
Date(int year, int month, int day, int hour, int minute, int second)
: 년월일 시분초를 입력해서 생성
2) 주요 메소드
String toString()
: 년월일 시분초를 문자열로 리턴int get?()
: ?에 해당하는 값을 정수로 리턴, deprecated
3) Java에서 데이터베이스 연동하는 프레임워크들이 데이터베이스의 Date 나 Time 과 매핑할 때 java.util.Date, java.sql.Date, java.sql.Time 등을 지원
- 최근에는 java.util.Date 보다는 java.sql.Timestamp 사용을 권장
2.java.util.Calendar
- 날짜와 시간을 저장하는 추상 클래스
1) 인스턴스 생성 static Calendar getInstance()
를 이용하면 현재 날짜 및 시간을 갖는 인스턴스를 생성해서 리턴- Calendar 클래스를 상속받은 클래스를 anonymous로 만들어서 인스턴스를 생성
2) 주요 메소드
long getTimeInMillis()
: 1970년 1월 1일 자정이후에 지나온 시간을 밀리초 단위로 리턴int get(Calendar의 field summary)
: field summary에 해당하는 값을 리턴void set(Calendar의 field summary, int value)
: field summary에 해당하는 값을 value로 설정
3) Calendar 를 상속받은 GregorianCalendar 클래스도 있음
4) 상위 클래스나 인터페이스를 만드는 목적 중의 하나가 동일한 작업을 수행하는 클래스들의 메소드 이름을 확정하기 위해서 만듭니다.
- List 인터페이스, Set 인터페이스, Map 인터페이스, Calendar 인터페이스가 대표적입니다.
Calendar cal = new GregorianCalendar(); //이 방식을 권장
GregorianCalendar cal = new GregorianCalendar();
3.Anonymous Class - 익명 클래스
- 클래스나 인터페이스를 상속받아서 인스턴스를 만들 때 상속받는 클래스를 만들지 않고 인스턴스를 바로 생성하는 문법
- 어떤 클래스나 인터페이스를 상속받아서 사용하는 것이 1번 뿐이라면 상속받는 클래스를 만드는 것은 자원의 낭비
- 클래스나 인터페이스는 한 번 만들어지면 메모리에서 소멸되지 않습니다.
- List 의 데이터를 정렬할 때 sort 메소드에 매개변수로
Comparator<E>
인터페이스를 대입해야 합니다.- 인터페이스이므로 인스턴스 생성을 못하기 때문에 sort 메소드에 대입을 할려면 상속을 받는 클래스를 만들고 인스턴스를 만들어서 대입해야 합니다.
4.날짜 클래스 사용
public static void main(String[] args) {
//java.util.Date 는 년도는 1900년 이후 지나온 년도, 월은 0부터 시작, 일은 1부터 시작
//2020년 1월 17일을 만들고자 하는 경우
//Date date = new Date(2020, 1, 17); //3920년 2월 17일이 됩니다.
Date date = new Date(120, 0, 17);
System.out.println(date);
//Calendar 클래스의 인스턴스를 생성
//Calendar 클래스는 추상 클래스 - 추상 클래스는 인스턴스를 생성할 수 없습니다.
//이렇게 작성을 하면 Calendar 클래스의 인스턴스를 만드는 것이 아니고
//Calendar 클래스를 상속받은 클래스의 Anonymous Class를 생성해서 인스턴스를 만든 후 리턴
//자바에서 인터페이스나 추상클래스를 리턴타입으로 하는 모든 메소드는 이 원리가 적용됩니다.
Calendar cal = Calendar.getInstance();
//toString이 너무 많은 양의 데이터를 리턴하도록 만들어져서 보기 어려움
//System.out.println(cal);
//필요한 데이터만 추출 - 월은 0부터 시작하기 때문에 출력할 때는 +1
System.out.println(cal.get(Calendar.MONTH) + 1);
//1월 부터 12월 까지의 날 수를 배열에 저장
//int [] months = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//2월의 날수
//months[1];
//프로그래밍의 편리성을 위해서 첫번째 위치에 의미없는 값을 삽입해서
//인덱스와 데이터의 위치를 맞추는 경우가 있습니다.
int [] months = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//2월의 날수
//months[2];
}
5.SimpleDateFormat
- Format으로 끝나는 클래스는 java.text 패키지에 존재하고 서식에 맞춘 문자열을 만들어주는 클래스
- DecimalFormat(숫자를 문자열), ChoiceFormat(실수 구간을 문자열로 - 숫자 데이터를 범주형으로 만들기), MessageFormat(폼에 데이터를 삽입) 등이 있습니다.
java.util.Scanner 클래스
- 입력 스트림으로부터 데이터를 읽어내기 위한 클래스
1.생성자
Scanner(InputStream is)
: is로 부터 데이터를 읽어 내기 위한 Scanner 객체를 생성- 키보드 스트림: System.in
2.주요 메소드
int nextInt()
: Enter 나 공백 앞까지 읽어서 정수로 변환한 후 리턴- Enter 나 공백 앞에 정수로 변환할 수 없는 데이터가 있으면 예외를 발생
String next()
: Enter 나 공백 앞까지 읽어서 문자열로 변환한 후 리턴- 공백 앞 까지 읽다보니 중간에 공백을 포함한 문자열은 나누어서 읽게 됩니다.
`String nextLine()* : Enter 까지 읽어서 문자열로 변환한 후 리턴
double nextDouble()
: 실수로 변환해서 리턴void close()
: Scanner 닫기, 이 메소드를 호출하지 않으면 메모리 정리가 이루어지지 않는다고(memory leak) 경고 발생
3.콘솔에서 키보드 입력의 문제점
- 키보드 입력을 하게되면 입력한 내용 전체를 버퍼에 저장
- 키보드 입력을 읽어가는 메소드들은 버퍼에서 필요한 만큼 가져가서 수행을 합니다.
- 숫자 데이터를 입력받고 바로 이어서 문자열을 입력받는 경우에 문제가 발생할 수 있는데 그 이유가 숫자를 입력하고 Enter를 눌러서 숫자 입력을 종료하게 되는데 숫자 데이터를 가져가는 메소드는 Enter는 버퍼에 남겨두고 가져갑니다.
- nextLine 메소드는 버퍼에 Enter가 남아있기 때문에 새로운 입력을 받지 않고 Enter를 가지고 가서 자신의 입력을 종료시킵니다.
- 이런 경우에 버퍼를 비울 수 있는 메소드가 있다면 버퍼를 비우고 입력을 받고 버퍼를 비울수 없다면 Enter를 입력받을 수 있는 메소드를 호출해주면 됩니다.
- 자바에서는 숫자 다음에 문자열을 입력받는 경우 입력받기 전에 Scanner.nextLine()을 호출해서 버퍼의 Enter를 삭제시킵니다.
C언어는 버퍼를 비울 수 있기 때문에 버퍼 비우는 함수를 호출한 후 다시 입력받고 파이썬 경우는 문자열을 입력받는 input() 만 제공
Thread
Program: 유사한 작업을 위한 file 의 집합
Process: 실행 중인 프로그램
- Process는 자신의 작업이 수행 중인 동안 쉬는 시간이 생기더라도 다른 프로세스에게 제어권을 넘기지 않습니다.
- 일반적인 함수나 메소드를 호출하는 것이 Process 입니다.
Thread: Process의 일부분으로 자원할당과 실행의 단위
- 독자적으로 실행할 수 는 없고 Process의 일부분으로만 실행 가능
- 한 번 실행하고 종료되면 재시작이 안됩니다.
- 자신의 작업이 실행 중인 동안 일정 시간 단위 또는 쉬는 시간이 생기면 다른 스레드에 제어권을 넘길 수 있습니다.
- 동시에 실행되는 것이 아니고 제어권을 넘겨서 다른 작업도 할 수 있다는 개념입니다.
Task: Process 와 Thread
1.여러 개의 Thread를 동시에 실행시켰을 때의 장점
- 일반적으로는 작업의 처리 속도가 빨라집니다.
- 자원을 효율적으로 사용할 수 있습니다.
2.여러 개의 Thread를 동시에 실행시켰을 때의 단점
- 여러 개의 Thread가 공유자원을 동시에 수정할려고 하는 부분을 제어해야 해서 복잡해 질 수 있음
- 너무 많은 Thread를 생성해서 실행하면 Thread 간의 이동하는 시간이 작업시간보다 길어져서 오히려 느려지는 현상이 발생할 수 있습니다.(Thrashing)
3.java.lang.Thread 클래스
- Thread를 위한 클래스
1) 생성자 Thread()
: 스레드의 이름을 jvm이 설정Thread(String name)
: 스레드 이름을 name으로 설정해서 생성Thread(Runnable r)
: r을 가지고 스레드를 생성Thread(Runnable r, String name)
: r을 가지고 스레드를 생성하고 이름은 name으로 설정
2) 메소드
static void sleep(int msec) throws InterruptedException
- 현재 스레드를 msec 만큼 대기시키는 메소드
- 사용을 할 때 InterruptedException을 처리 해 주어야 합니다.
void run()
: 스레드로 수행할 내용을 가지는 메소드void start()
: 스레드로 실행하도록 하는 메소드getName(), setName(String name): 스레드 이름 가져오기와 설정
getPriority(), setPriority(int priority): 스레드의 우선 순위 가져오기와 설정
isAlive(): 실행 중인 상태인지 확인할 수 있는 메소드
4.Runnable 인터페이스
- public void run(): 스레드로 수행할 내용을 가지는 메소드
5.스레드를 만들고 실행
1) Thread 클래스를 상속하는 방법
- Thread 클래스를 상속받는 클래스를 만들고 스레드로 수행할 내용을 run 메소드에 작성
- 앞에서 만들어진 클래스의 인스턴스를 만들고 start()를 호출
2) Runnable 인터페이스를 구현하는 방법
- Runnable 인터페이스를 implements 한 클래스를 만들고 스레드로 수행할 내용을 run 메소드에 작성
- 앞에서 만든 클래스의 인스턴스를 생성
- 앞에서 만든 인스턴스를 Thread 클래스의 생성자에 대입해서 Thread 클래스의 인스턴스를 만들고 start()를 호출
3) 스레드로 동작해야 하는 필수적인 작업은 네트워크 작업입니다.
- 안드로이드나 iOS는 네트워크 전송에 스레드를 사용하지 않으면 에러
4) 스레드 생성 및 실행 실습
//하나의 파일에 클래스를 2개 만든 다면
//public class는 1개이어야 하고 파일이름은 public class의 이름이어야 합니다.
//Runnable 인터페이스를 implements 한 클래스
class RunnableImpl implements Runnable{
//스레드로 수행할 내용을 가지는 메소드
public void run() {
}
}
public class Main2 {
public static void main(String[] args) {
RunnableImpl r1 = new RunnableImpl();
//r1 과 r2는 같은 기능
Runnable r2 = new Runnable() {
public void run() {
//Hello Runnable 을 1초마다 5번 출력
try {
for(int i=0; i<5; i=i+1) {
Thread.sleep(1000);
System.out.println("Hello Runnable");
}
}catch(Exception e) {
System.out.println("스레드 예외:" + e.getMessage());
}
}
};
//Thread 클래스의 인스턴스를 생성
Thread th = new Thread(r2);
//r2의 run 메소드를 스레드로 수행
th.start();
Thread th1 = new Thread() {
public void run() {
//Hello Thread 을 1초마다 5번 출력
try {
for(int i=0; i<5; i=i+1) {
Thread.sleep(1000);
System.out.println("Hello Thread");
}
}catch(Exception e) {
System.out.println("스레드 예외:" + e.getMessage());
}
}
};
//스레드로부터 상속을 받은 경우에는 바로 start() 호출
th1.start();
}
}
6.스레드 상태 및 수명주기
1) new: 스레드가 만들어지고 실행 대기 중인 상태 - start를 호출하고 실행 대기
2) runnable: 실행 중인 상태
3) waiting: 대기 중인 상태인데 이 때는 다른 스레드가 notify() 나 notifyAll()을 호출해주면 다시 실행
4) timed_waiting: 자신의 실행 시간이 오기를 기다리고 있는 상태, 일정 시간 단위로 작업을 수행하는 time sharing system 에서 자신의 차례를 기다기고 있는 상태
5)block: 입출력 요청이 있는 경우 요청을 처리하기 위해서 cpu를 사용할 필요가 없기 때문에 block 상태로 작업을 수행하다가 입출력 요청이 끝나면 cpu에 알려서 작업을 계속 수행할 수 있는 상태
6)terminated: thread가 종료된 상태
- run 메소드의 수행이 종료되었거나 다른 스레드에 의해서 강제로 종료된 경우
스레드는 한 번 종료되면 다시 실행시킬 수 없습니다.
7.Daemon Thread
Daemon Thread가 아닌 스레드가 하나도 없으면 자동으로 실행을 중지하는 스레드
일반 스레드의 보조적인 역할을 수행하는 스레드
일반 스레드는 자신의 run 메소드가 종료되거나 다른 스레드에서 강제로 종료시키지 않으면 자신의 작업을 계속 수행합니다.
- 다른 스레드에서 예외가 발생해도 자신의 작업은 계속 수행합니다.
대표적인 데몬 스레드로는 main 메소드, 일반 응용 프로그램에서 임시 저장 기능 이나 네트워크 프로그램에서 중간 중간 commit 하는 작업 등이 있습니다.
데몬 스레드를 만드는 방법은 start()를 호출하기 전에 setDaemon(true)롤 호출하면 됩니다.
데몬을 설정했을 때와 그렇지 않을 때의 수행 내용을 비교해보아야 합니다.
public static void main(String[] args) {
Thread th = new Thread() {
public void run() {
try {
for(int i=0; i<10; i=i+1) {
Thread.sleep(1000);
System.out.println("데몬 스레드");
}
}catch(Exception e) {
}
}
};
//th를 데몬으로 설정 - 다른 작업이 없으면 자동으로 종료
//프로그램에서는 데몬 스레드가 더 많이 사용됩니다.
//start 하기 전에 데몬으로 설정
th.setDaemon(true);
th.start();
//th.setDaemon(true);
try {
Thread.sleep(3000);
}catch(Exception e) {
System.out.println(e.getMessage());
}
System.out.println("메인 종료");
}
8.스레드의 우선 순위
- 2개 이상의 스레드가 동작 중인 경우 어떤 스레드가 먼저 수행될 지 또는 자주 수행될지는 알 수 없습니다.
- 이런 특정 스레드를 먼저 또는 자주 수행하도록 할 수 있는 기능이 우선순위 부여입니다.
- 우선순위를 설정하도라도 반드시 우선순위에 따라 동작하지 않습니다.
- 확률적으로 우선순위가 높으면 먼저 또는 자주 수행되는 것입니다.
- 우선 순위를 가져오는 메소드가 int getPriority() 이고 우선순위를 설정하는 메소드가 void setPriority(int priority)
- setPrority의 매개변수는 정수를 대입받도록 되어 있지만 실제로는 Thread 클래스의 Field Summary 인 MAX_PRIORITY, NORM_PRIORITY, MIN_PRIORITY를 설정하도록 합니다.
- 위처럼 설정하라고 하는 이유는 2가지 인데 첫번째는 우선순위는 일정한 범위가 있습니다.
- 아무 정수나 대입하면 안됩니다.
- 두번째 이유는 스레드의 우선순위 범위는 운영체제마다 다릅니다.
- 윈도우는 1-10까지 이고 UNIX에서는 1-7까지 입니다.
- 10이라는 숫자를 대입하면 윈도우에서는 있는 범위 내의 숫자이기 때문에 아무런 문제가 되지 않지만 UNIX에서는 없는 숫자가 됩니다.
- Thread.MAX_PRIORITY 로 설정하면 jvm이 알아서 windows에서 10 UNIX에서는 7로 설정을 합니다.
- 자바가 모든 운영체제에서 동작하는 애플리케이션을 한 번만 제작해도 되는 이유는 java의 옵션들을 사용한다면 값은 jvm이 운영체제 별로 알아서 할당을 합니다.
- jdk(개발도구) 자체는 운영체제 별로 분류가 되어 있지 않지만 실행을 해주는 jvm이 운영체제 별로 별도로 존재해서 jvm이 알아서 옵션 값들을 설정합니다.
- Field Summary는 메소드들에서 사용하기 위한 옵션 값들입니다.
//class 를 만드는 경우는 대부분 인스턴스를 2개 이상 만드는 경우
class Threadext extends Thread{
public void run() {
//스레드 자신의 이름을 10번 출력(1초마다 쉬면서)
for(int i=0; i<10; i=i+1) {
try {
Thread.sleep(1000);
System.out.println(getName());
}catch(Exception e) {}
}
}
}
public class Main4 {
public static void main(String[] args) {
Threadext th1 = new Threadext();
Threadext th2 = new Threadext();
Threadext th3 = new Threadext();
//스레드 우선 순위 설정 : 확률적으로 th3 이 먼저 시작할 가능성이 높아집니다.
th1.setPriority(Thread.MIN_PRIORITY);
th2.setPriority(Thread.NORM_PRIORITY);
th3.setPriority(Thread.MAX_PRIORITY);
th1.start();
th2.start();
th3.start();
}
}
9.스레드의 강제 종료
스레드를 강제로 종료할 때는 스레드 인스턴스가 interrupt()라는 메소드를 호출해주면 되는데 이 때 스레드의 run 메소드에 InterruptedException이 발생했을 때 run 메소드를 종료하도록 코드를 만들어주어야 합니다.
Threadext 클래스에서 catch 구문에서 return을 생략하고 실행해보고 return을 넣고 실행
- 두번째 스레드의 이름인 thread-1 이 계속 출력되기도 하고 3초 후에 출력이 안되기도 합니다.
- return 이 있고 없고에 따라서 스레드가 강제로 종료되기도 하고 그렇지 않기도 합니다.
//class 를 만드는 경우는 대부분 인스턴스를 2개 이상 만드는 경우
class Threadext extends Thread{
public void run() {
//스레드 자신의 이름을 10번 출력(1초마다 쉬면서)
for(int i=0; i<10; i=i+1) {
try {
Thread.sleep(1000);
System.out.println(getName());
}
//InterruptedException이 발생했을 때 return 하도록 만들어주면 스레드가
//강제로 종료될 수 있습니다.
catch(InterruptedException e) {
return;
}
}
}
}
public class Main4 {
public static void main(String[] args) {
Threadext th1 = new Threadext();
Threadext th2 = new Threadext();
Threadext th3 = new Threadext();
//스레드 우선 순위 설정 : 확률적으로 th3 이 먼저 시작할 가능성이 높아집니다.
th1.setPriority(Thread.MIN_PRIORITY);
th2.setPriority(Thread.NORM_PRIORITY);
th3.setPriority(Thread.MAX_PRIORITY);
th1.start();
th2.start();
th3.start();
try {
Thread.sleep(3000);
//th2 스레드에게 인터럽트 발생
th2.interrupt();
}catch(Exception e) {}
}
}
10.Thread의 실행 제어
void join(int millis, int nanos)
: 입력한 시간동안만 스레드를 수행- 윈도우즈와 같은 클라이언트 운영체제에서는 1/20 초 이하의 설정은 의미가 없습니다.
void suspend()
: 작업을 일시 정지void resume()
: 일시 정지된 스레드가 작업을 계속void yield()
: 실행 상태를 양보하고 대기 상태로 전환
11.ThredGroup
- Thread를 묶어서 관리하기 위한 클래스
- 몇 몇 메소드가 특정 운영체제에서 제대로 동작하지 않아서 비추천
- List 등을 이용해서 그룹화하기를 권장
'Language_Study > JAVA' 카테고리의 다른 글
[JAVA, App] 16.이벤트처리 (0) | 2020.12.27 |
---|---|
[JAVA, App] 15.MutualExclusion (0) | 2020.12.27 |
[JAVA, App] 13.Framework (0) | 2020.12.25 |
[JAVA, App] 12.Interface (0) | 2020.12.25 |
[JAVA, App] 11.Package (0) | 2020.12.25 |