반응형

**Properties

=>key Value를 쌍으로 저장하는 자료구조

=>Map은 모든 자료형을 사용할 수 있지만 PropertieskeyValue 모두 String만 가능

=>자료형이 결정되어 있어서 앞에 나온 자료구조 들과 다르게 Generics을 이용하지 않습니다.

=>환결설정을 xml이나 텍스트 파일에 작성해두고 그 내용을 읽어서 프로그램에 적용하고자 하는 용도로 많이 사용

=>Spring같은 프레임워크에서는 메시지 출력 등에 이용됩니다.

 

1.주요 메소드

String setProperty(String key, String value) : 프로퍼티 저장

String getProperty(String key) :key에 해당하는 프로퍼티를 가져옵니다.

 

파일에 저장

void store(OuputStream stream, String comment) :comment와 함께 stream(파일이나 네트워크)에 내용을 저장

파일 같은 것을 저장할  수 있ㄷ.

 

void storeToXML(OuputStream stream, String comment) :comment와 함께 stream xml 형식으로 저장

 

2. XML(eXtensible Markup Language):태그 형식으로 표현하는데 해석을 브라우저가 하지 않고 개발자나 설정된 스키마가 해석하는 형식의 문석

이전에 web에서 데이터를 전송하기 위한 표준으로 사용되었고 설정 파일에 많이 이용되었습니다.

HTML(View)은 비구조적이고 느슨한 문법을 적용하지만 XML(Data)은 구조적이고 엄걱한 문법을 제공

XML은 데이터의 역할이고

ajaxxml의 약자이다.

html은 실시간 신문 기자

rss ->

xmljson형태로 데이터가 되여있다.

xml로 하면 여기저기 schema로 한다.

 

@ java에서는 어노테이션

python에서는 decorator

java , python설정이 같으면 나머지 코드는 부착한다.

python 에서는 static을 몰라서 @static으로 하거나 class를 할경우에도 @class 라고 한다.

어떤 설정을 해야 하는데 만들기 힘들어서 xml로 해서 코드가 바꾼다.

설정파일 이 들어가는데 => xml아님 json(decorator)이다.

https://developers.kakao.com/features/platform

 

요청을 할때 json하면 json하고 xml하면 xml이다.

 

실시간 제공은 거의 xml이다. http://data.go.kr/

 

3.현재 작업디텍토리 사용

./ :현재 작업 디렉토리, 생략하고  파일 경로만 적으면 현재 작업디렉토리에서 작업을 합니다.

명령어를 입력할 때는 Mac에서는 ./를 생략하면 명령어가 없다고 나옵니다.

 

 

4.실습 -프로퍼티를 만들고 저장하기 : 현재 프로젝트 디렉토리에 파일 생성 여부 확인

public class PropertiesMain {

 

           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");

                       String age = props.getProperty("age");

                      

                       System.out.println(name);

                       System.out.println(age);

                       //자바는 없으면 null로 뜬다.

                      

                       //props를 현재 디렉토리에 temp.xml파일로 내보내기

                       try {

                                  props.storeToXML(new FileOutputStream("temp.xml"), "주석");

                       }catch(Exception e) {

                                  System.out.println("예외 발생:" +e.getMessage());

                       }

           }

 

}

 

 

 

props.storeToXML(new FileOutputStream("./temp.xml"), "주석");

cmd창에서 mac , unix일 경우  ./ 있어야 검색 가능할 수 도있다.

 

 

** 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내부를 수정하는 것은 가능

final은 전체를 바꾸는 것이 안되는 것이지 부분적인것 바꿀 수 없는 것은 아니다.

 

List<String> imList = Collections.unmodifiableCollection(list);

//imList는 내부 데이터를 수정하지 못합니다.

 

=>checked를 추가하면 1가지 데이터 타입만 사용이 가능

이 부분은 제너릭을 적용하면 동일한 효과를 만들 수 있음

제너릭을 적용하지 않고 만들어진 자료구조라면 이 메소드를 이용해서 제너릭을 적용하는 효과를 만들 수 있습니다.

제너릭은 인스턴스를 만들 때 자료형을 결정하는 것으로 자료구조 클래스에서 주로 이용

List<String> list = new ArrayList<String>();//list에는 String 만 저장 가능

 

List list1 = new ArrayList();//list1에는 모든 자료형의 데이터를 저장할 수 있습니다.

자동으로 ObjecctList가 됩니다.

이런 경우 String만 저장하도록 변경하고자 하는 경우에 checked를 사용

 

List list2 =  Collections.checkedCollection(list1, String.class);

list2String만 저장 가능

기존데이터를 유지하면서 하는 것이다.

 

**java.util.Random ->숫자

=>랜덤한 값을 생성해주기 위한 클래스

=>랜덤한 값을 seed(난수표)에서 데이터를 순서대로 하나씩 가져오는 개념

seed가 고정이 되면 랜덤 값은 일정한 패턴으로 리턴됩니다.

random_state ->seed설정하는 것

 

1.생성자

Random():현재 시간을 기준으로 seed를 설정, 생성될 때 마다 seed가 변경될 가능성이 높음

Random(long seed) :seed를 매개변수로 설정

 

2.메소드

float nextFloat(): 실수형 난수 생성해서 리턴

int nextInt(): 정수형 난수 생성해서 리턴

int nextInt(int n ):          %n한 결과의 난수를 생성

로또 번호라면  45+1

void setSeed(long seed) :seed를 변경

 

3.java.util.UUID클래스->문자도 가능

=>이 클래스의STATIC 메소드인 randomUUID()를 호출하면 랜덤한 문자열을 생성

결과를 toString()으로 확인하면 랜덤한 문자열을 확인할 수 있습니다.

phone

itunes 일련번호 클릭하면 랜덤한 아이디

iphone에서 SEID

SEED가 고정되면 숫자가 순서대로 나온다.

 

random_state = 1; //seed설정하는 것이다. 데이터  뽑을 때 똑 같다.

잘못 되면 overfit같은 경우가 있을 수 있어서 데이터를 바꿔가면서 해야 한다.

random_ =>seed설정이다.

 

randomseed가 있으면 순서대로 준다.

 

 

 

  

 

random끝까지 하다가 오래하면 터지는 것은 seed를 그대로 나둬야 하는데 확률을 reset되서 확률이 낮아진다.

이벤트 random을 할 경우 첫날 좋은 것 나오면

균등하게 하는지 아니면 뒤쪽에서 하는지 확률을 조작한다.

게임 등에서는 완전한 random을 사용하지 않는다.

seed를 설정해서 어느 정도에 터지 게끔 한다.

여러가지 적용해서 해야 한다.

 

고스톱은 점수를 계산해야 하는데

포커는 규칙을 찾으면 된다.

규칙을 먼저 출력하고 룰에서 우선순위 비교해서 한다.

 

4.랜덤 실습 1

public class RandomMain {

 

       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 = {"빨강","파랑","녹색"};

               //배열에서 배열만의 인덱스가 랜덤하게 나오도록 r1.nextInt(colors.length)

               //배열의 인덱스에 허용

               String color = colors[r1.nextInt(colors.length)];

               System.out.println("color: " +color);

              

               //빨강을 많이 나오게 하는 방법 1:

               String [] colors1 = {"빨강","파랑","녹색","빨강"};

               for(int i = 0 ; i < 10 ; i++) {

                      String color1 = colors1[r1.nextInt(colors1.length)];

                      System.out.println("color1: " +color1);

               }

              

               //방법 2

               String [] colors2 = {"빨강","파랑","녹색"};

               ///4 나머지 : 0 , 1,2,3 % 3 : 0 , 1 ,2,0

               String color2 = colors2[r1.nextInt(4) % 3]; //1 많이 나오게끔 한다.

              

               //복원추출은 같은 나올 있다.

              

               //비복원 추출 - 배열 사용하면 안된다  중간에 데이터를 지울 없다.

               //비복원 추출 - 훈련데이터 테스트데이트 샘플링, 로또 , 고스톰, 포커

               List<String> list = new ArrayList<String>();

               //1-45까지 저장

               for(int i = 1; i <= 45; i++) {

                      list.add(i + "");

               }

               //20개의 숫자를 비복원 추출

               //똑같은 다시 나오면 안되면 추가하고 제거한다. 나온 것을 꺼집어 내고 해야 한다.

               for(int i = 0; i < 20 ; i ++) {

                      //list사이즈 내에서 데이터를 추출

                      String x = list.get(r1.nextInt(list.size()));// 0 -44까지

                      // 데이터를 제거

                      list.remove(x);

                      //정수를 주면 정수번째로 나와서 오류난다. 그래서 string으로 해야한다.

                      System.out.print( x+ "\t");

               }

               System.out.println();

              

               //랜덤한 문자열 만들기 -이미지 파일 등을 업로드 봤을 파일이름 그리고 유저를 구분하기 위한 이름등을 만들 이용

               String name = UUID.randomUUID().toString();

               System.out.println(name);

       }

      

}

 

5. 랜덤 실습 2

public class Chery {

 

       public static void main(String[] args) {

               String [] image = {"!" , "@" ,"#" ,"$","%" ,"^"};

              

               //Raddom 객체 생성

               Random r = new Random();

               List<String> list = new ArrayList<String>();

               for(int i = 0; i < 3 ; i++) {

                      String temp =image[r.nextInt(image.length)];

                      System.out.print(temp + "\t");

                      list.add(temp);

               }

               System.out.println();

              

               if(list.get(0) == list.get(1) && list.get(0) == list.get(1)) {

                      System.out.println("3개가 모두 일치");

               }else if(list.get(0) == list.get(1) ) {

                      System.out.println("앞의 2개가 잋리");

               }else {

                      System.out.println("");

               }

              

       }

 

}

 

 

**날짜 관련 클래스

1.java.util.Date 클래스

=>날짜와 시간을 저장하기 위한 클래스

1)생성자

Date(): 현재 날짜 및 시간을 가지고 생성

Date(long timeMillist) : 1970년부터 11일 자정 이후부터 지나온 시간을 밀리초 단위로 입력해서 생성

Date(int year, int month, int day) : 년월일을 입력해서 생성 ,년도는 1900년 이후에 지나온 시간,월은 0부터 시작하기 때문에 하나 적게 설정, day는 일반적인 형태로 설정

2020s117 :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에서 데이터베이스 연동하는 프레임워크들이 데이터베이스의 DateTime과 매핑할 때

java.util.Date, java.util.Date, java.sql.Time등을 지원

최근에는 java.util.Date보다는 java.sql.Timestamp사용을 권장

 

2.java.util.Calendar

=>날짜와 시간을 저장하는 추상 클래스

1)인스턴스 생성

static Calendar getInstance()를 이용하면 현재 날짜 및 시간을 갖는 인스턴스를 생성해서 리턴

Calendar 클래스를 상속받은 클래스 anonymous로 만들어서 인스턴스를 생성

 

2)주요 메소드

long getTimeInMillis(): 197011일 자정이후에 지나온 시간을 밀리초 단위로 리턴

int get(Calendarfiled summary) :field summary에 해당하는 값을 리턴

void set(Calendarfield summary, int value ): field summary에 해당하는 값을 value로 설정

 

3)Calendar를 상속 받은  GregorianCalendar클래스도 있음

 

4)상위 클래스나 인터페이스를 만드는 목적 중의 하나가 동일한 작업을 수행하는 클래스들의 메소드 이름을 확정하기 위해서 만듭니다.

List인터페이스 , Set인터페이스, Map인터페이스,Calendar인터페이스가 대표적입니다.

 

Calender cal = new GregorianCalendar();//이 방식을 권장

GregorianCalendar cal = new GregorianCalendar();

 

3.  Anonymous Class - 익명 클래스

=>클래스나 인터페이스를 상속받아서 인스턴스를 만들 때 상속받는 클래스를 만들지 않고 인스턴스를 바로 생성하는 문법

=>어떤 클래스나 인터페이스를 상속받아서 사용하는 것이 1번 뿐이라면 상속받는 클래스를 만드는 것은 자원의 낭비

클래스나 인터페이스는 한 번 만들어지면 메모리에서 소멸되지 않습니다.

클래스 만들지말고 인스턴스 만들어서 사용하라

=>List의 데이터를 정렬할 때 sort 메소드에 매개변수로  Comparator<E>인터페이스를 대입해야 합니다.

인터페이스이므로 인스턴스 생성을 못하기 때문에 sort멘소드에 대입을 할려면 상속을 받는 클래스를 만들고 인스턴스를 만들어서 대입해야 합니다.

 

Interface Comparator<T>

상속 받은 걸 만들어 줘야 하고

Comparator implements한 클래스를 만든다.

 

앞에 5개 일경우

1 ~ 5

0 ~ 4

 

public class StringComp implements Comparator<String> {

 

       @Override

       public int compare(String o1, String o2) {

               return o1.compareTo(o2);

       }

 

}

 

public class ListSortMain {

       public static void main(String[] args) {

               //문자열 List 생성하고 데이터를 저장

               ArrayList<String> list = new ArrayList<String>();

               list.add("야구");

               list.add("농구");

               list.add("축구");

               list.add("농구");

              

              

               //Comparator인터페이스를 implements 클래스의 인스턴스를 만들어서 정렬

               StringComp comp = new StringComp();

               //데이터 정렬 -Comparator 매개변수로 요구

               list.sort(comp);

              

              

               //Comparator Anonymous Class만들기

               //Comparator c = new Comparator();//오류다  인터페이스 이기 때문이다.

               //클래스 없이 Comparator 인터페이스를 구현한 클래스의 인스턴스를 바로 만들기

               // 문법의 확장인 람다가 자바의 함수형 프로그래밍을 지원

               Comparator<String> c = new Comparator<String>() {

 

                      @Override

                      public int compare(String o1, String o2) {

                             //desc

                             return o2.compareTo(o1);

                      }

                     

               };

              

               list.sort(c);

              

               //데이터 출력

               for(String temp :list) {

                      System.out.print(temp+"\t");

               }

       }

}

4.실습

public class DateMain {

 

       public static void main(String[] args) {

               //java.util.data 년도는 1900 이후 지나온 년도 ,월은 0부터 시작 ,일은 1부터 시작

               //2020 1 17일을 만들고자 하는 경우

               Date date = new Date(2020, 1, 17); //3929 2 17일이 됩니다.

               System.out.println(date);//Tue Feb 17 00:00:00 KST 3920

              

               date = new Date(120, 0 , 17);

               System.out.println(date); //Fri Jan 17 00:00:00 KST 2020

              

               //Calendar클래스의 인스턴스를 생성

               //Calendar 클래스는 추상 클래스 - 추상 클래스는 인스턴스를 생성할 없습니다.

               //이렇게 작성을 하면 calender클래스의 인스턴스를 만드는 것이 아니고

               //calendar클래스를 상속받은 Anonymous Class 생성해서 인스턴슬르 만든 리턴

               //자바에서 인터페이스나 추상클래스를 리턴타입으로 하는 모든 메소드는 원리가 적용됩니다.

               Calendar cal= Calendar.getInstance();

               //toString 너무 많은 양의 데이터를 리턴하도록 만들어져서 보기 어려움

               //System.out.println(cal);

       //java.util.GregorianCalendar[time=1579231502749,areFieldsSet=true,

       //areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Seoul",

       //offset=32400000,dstSavings=0,useDaylight=false,transitions=22,lastRule=null],

       //firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2020,MONTH=0,WEEK_OF_YEAR=3,

       //WEEK_OF_MONTH=3,DAY_OF_MONTH=17,DAY_OF_YEAR=17,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=3,

       //AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=25,SECOND=2,MILLISECOND=749,

               //ZONE_OFFSET=32400000,DST_OFFSET=0]

              

               //필요한 데이터만 추출 - 월은 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];

              

               //프로그램의 편리성을 위해서 첫번째 위치에 의미없는 값을 삽입해서

               //인덱스와 데이터의 위치를 맞추는 경우가 있습니다.

               //프로그래밍 에서 메모리 절약을 위해서 0부터 하지만

               //개발 할때는 index맞추는 것이 좋다.

               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(폼에 데이터를 삽입)등이 있습니다.

{1} 1번 데이터가 삽입된다.

 

범주형은 선택할 있는 것을 제한둔다. 조건문으로 해도된다.

0 ~ 59 f

60 ~ 69 d

점수 구간에 들어가면 범주형 if로도 가능하다.

데이터를 분석하는것

Strin gender ; =>enum

gender

값을 제한 하는 것을 범주혹은 Category라고 한다. 특정한 값만 쓸수 있게끔

분석 ->chart textMining

1 2를 차트 할때 남여로 바꾸는 것으로 해야 한다. 범주형

 

MessageFormat

워드 엑셀 매핑 시키는 것 라벨 기능 데이터를 입력해서 차곡차곡 쌓아 주는 것

 

회귀는 음수가 없다 . 빨간색으로 하던지 괄호 하던지 한다.

엑셀 에 서식

 

**java.util.Scanner클래스

=>입력 스트림으로부터 데이터를 읽어내기 위한 클래스

1.생성자

Scanner(InputStream is): is로 부터 데이터를 읽어내기 위한 Scanner객체를 생성

=>키보드 스트림 : System.in

InputStream -입력받을 수 있는 객체

 

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()만 제공

java에서는 int하고 문자열 시 문제 생긴다.

 

 

**Thread

=>Program:유사한 작업을 위한 file의 집합

=>Process:실행 중인 프로그램

Process는 자신의 작업이 수행 중인 동안 쉬는 시간이 생기더라도 다른 프로세스에게 제어권을 넘기지 않습니다.

일반적인 함수나 메소드를 호출하는 것이 Process입니다.

 

=>Thread :Process의 일부분으로 자원할당과 실행의 단위

독자적으로 실행할 수 없고 Process의 일부분으로만 실행가능

한번 실행하고 종료되면 재시작이 안됩니다.

재시작할려면 Process 새로 만들거나 재시작해야 한다.

자신의 작업이 실행 중인 동안 일정 시간 단위 또는 쉬는 시간이 생기면 다른 스레드에 제어권을 넘길 수 있습니다.

동시에 실행되는 것이 아니고 제어권을 넘겨서 다른 작업도 할 수 있다는 개념입니다.

쉬는 시간동안 다른 것 하니깐 빨라진 것처럼 보인다.

 

=>Task :ProcessThread

 

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를 생성

Thread(Runnable r, String name) : r을 가지고 스레드를 생성하고 이름은 name으로 설정

 

2)메소드

=>static void sleep(int msec) throws InterrupedExption

현재 스레드를 msec 만큼 대기시키는 메소드

사용을 할 때 InterruptedExcption을 처리 해 주어야 합니다.

 

=>vid run() ; 스레드로 수행할 내용을 가지는 메소드

실행이 안된다.

 

=>void start(): 스레드를 실행하도록 하는 메소드

 

=> getName(), setName(String name) :스레드 이름 가져오기와 설정

=> getPriority(),SetPriority(int priority) : 스레드의 우선 순위 가져오기와 설정

=>isAlive(): 실행중인 상태인지 확인할 수 있는 메소드 ->boolean

 

4. Runnable인터페이스

=>public void run();스레드로 수행할 내용을 가지는 메소드

 

 

5.스레드를 만들고 실행

1)Thread클래스를 상속하는 방법

=>Thread클래스를 상속받는 클래스를 만들고 스레드로 수행할 내용을 RUN메서드에 작성

=>앞에서 만들어진 클래스의 인스턴스를 만들고 START()를 호출

 

 

2)RUNNABLE 인터페이스를 구현하는 방법

=>Runnable 인터페이스를 implements한 클래스를 만들고 스레드로 수행할 내용을  run메소드에 작성

=>앞에서 만든 클래스의 인스턴스를 생성

=>앞에서 만든 인스턴스를 Thread클래스의 생성자에 대입해서 Thread 클래스의 인스턴스를 만들고 start()호출

runnablerun밖에 없고 thread에 가야 start가 있다.

 

 

3)스레드로 동작해야 하는 필수적인 작업은 네트워크 작업입니다.

안드로이드나 ios는 네트워크 전송에 스레드를 사용하지 않으면 에러

annanmys고려해야 하고 한파일에 클래스를 두개 만들어도 된다.

모든 언어가 보통 2가지 방법이 있다. 클래스로 부터 상속 받아서 하는 방법과 또 한가지 더 있다.

쉬는 동안 다른 thread에 간다.

 

4).스레드 생성 실습

public class ThreadEx extends Thread {

 

       public void run() {

               //1초마다 Hello Thread라는 문자열을 10 출력

               for (int i = 0; i < 10; i++) {

                      System.out.println("Hello Thread");

                      //한개 스레드 1 대기

                      try {

                             Thread.sleep(1000);

                      } catch (InterruptedException e) {

                             System.out.println(e.getMessage());

                      }

               }

       }

}

 

public class Main1 {

 

       public static void main(String[] args) {

               //ThreadEx 인스턴스 2개를 생성

               ThreadEx th1 = new ThreadEx();

               ThreadEx th2 = new ThreadEx();

              

               //일반적인 메소드 호출 :하나의 메소드 수행이 종료되고 다른 메소드가 수행된다.- 20

               //th1.run();

               //th2.run();

              

              

               //스레드 실행 :하나의 스페드가 쉬는 시간이 생기면 다른 스레드의 작업을 처리

               th1.start();

               th2.start();

               //동시에 진행 되는 것이 아니라 시간이 워낙 짧아서 동시에 진행하는 것처럼 보인다.

              

       }

 

}

 

//하나의 파일이 클래스를 2 만든 다면

//PUBLIC class 1개이어야 하고 파일 이름은 public class이름이어야 한다.

 

//Runnable인터페이스를 implements 클래스

class RunnableImple implements Runnable{

       //스레ㅔ드 수행할 내용을 가지고 있는 메소드

       @Override

       public void run() {

               // TODO Auto-generated method stub

              

       }

      

}

 

public class Main2 {

       public static void main(String[] args) {

               RunnableImple r1= new RunnableImple();

              

               //r1 R2 같은 기능

               Runnable r2 = new Runnable() {

 

                      @Override

                      public void run() {

                             // Hello Runnable 1초마다 5 출력

                             try {

                                    for (int i = 0; i < 5; i++) {

                                           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++) {

                                           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: 강제로 대기 중인 상태인데 이 떄는 다른 스레드가 notity()notifyAll()을 호출해주면 다시 실행

어떤 신호가 오기를 기다리는 상태

4).timed_waiting:자신의 실행 시간이 오기르 기다리고 있는 상태 ,일정 시간 단위로 작업을 수행하는 time sharing system에서 자신의 차례를 기다리고 있는 상태

5)block: 입출력 요청이 있는 경우 요청을 처리하기 위해서 cpu를 사용할 필요가 없기 때문에 block상태로 작업을 수행하다가 입출력 요청이 끝나면 cpu에 알려서 작업을 계속 수행할 수 있는 상태

6)terminate:thread가 종료된 상태

run메소드의 수행이 종료되었거나 다른 스레드에 의해서 강제로 종료된 경우

 

=>스레드는 한 번 종료되면 다시 실행 시킬 수 없습니다. terminate상태로 가면 끝이다.

 

 

7.Daemon Thread

=>Daemon Thread가 아닌 스레드가 하나도 없으면 자동으로 실행을 중지하는 스레드

=>일반 스레드의 보조적인 역할을 수행하는 스레드

=>일반 스레드는 자신의 run메소드가 종료되거나 다른 스레드에서 강제로 종료시키지 않으면 자신의 작업을 계속 수행합니다.

다른 스레드에서 예외가 발생해도 자신의 작업은 계속 수행합니다.

=>대표적인 데몬 스레드가 main메소드 , 일반 응용 프로그램에서 임시 저장 기능이나 네트워크 프로그램에서 중간 중간 commit하는 작업 등이 있습니다.

main 다른 작업이 아무것도 없으면 알아서 종료된다.

 

=>데몬 스레드를 만드는 방법은 start()를 호출하기 전에 setDaemon(true)를 호출하면 됩니다.

=>데몬을 설정했을 때와 그렇지 않을 때의 수행 내용을 비교해보아야 합니다.

public class Main3 {

       public static void main(String[] args) {

              

               Thread th = new Thread() {

                      public void run() {

                             try {

                                    for(int i = 0; i < 10 ; i++) {

                                           Thread.sleep(1000); //10

                                           System.out.println("데몬 스레드");

                                    }

                             }catch(Exception e) {

                                    System.out.println(e.getMessage());

                             }

                      }

               };

              

               //일반 스레드는 중지하거나 interrupt emd 생기지 않으면 절대 종료하지 않는다.

               //windows죽어도 프로세스 상에는 살아 있는 것이 있다.

               //무한 반복문은 영원히 죽는다.

               //자기 작업이 끝날 까지 죽는다.

               //다른 스레드가 없으면 종료되도록 만들 힜다.

               //th 데몬으로 설정 -다른 작업이 없으면 자동으로 종료

               //프로그램에서는 데몬 스레드가 많이 사용됩니다.

               //sart하기 전에 데몬으로 설정

               th.setDaemon(true);

               th.start();

               //th.setDaemon(true);

              

               //3초동안 실행해다가 죽는다.

               try {

                      Thread.sleep(3000);

               }catch(Exception e) {

                      System.out.println(e.getMessage());

               }

               System.out.println("메인 종료");

       }

}

 

 

8.스레드의 우선순위

Field Summary

=>2개 이상의 스레드가 동작 중인 경우 어떤 스레드가 먼저 수행될 지 또는 자주 수행될지는 알 수 없습니다.

=>이런 특정 스레드를 먼저 또는 자주 수행하도록 할 수 있는 기능이 우선순위 부여입니다.

우선순위를 설정하더라도 반드시 우선순위에 따라 동작하지 않습니다.

확률적으로 우선순위가 높으면 먼저 또는 자주 수행되는 것입니다.

=>우선 순위를 가져오는 메소드가 int getPrority()이고 우선순위를 설정하는 메소드가 void setPrority(int priority)

=>setPrority의 매개변수는 정수를 대입받도록 되어있지만 실제로는 Thread 클래스의 Field SummaryMAX_PRORITY, NORM_PRIORITY ,MIN_PRIORITY를 설정하도록 합니다.

=>위처럼 설정하라고 하는 이유는 2가지 인데 첫번째는 우선순위는 일정한 범위가 있습니다.

아무 정수나 대입하면 안됩니다.

두번째 이유는 스레드의 우선순위 범위는 운영체제마다 다릅니다.

윈도우는 1-10까지 이고 unix에서는 1- 7까지 입니다.

10이라는 숫자를 대입하면 윈도우에서는 있는 범위내의 숫자이기 때문에 아무런 문제가 되지 않지만 unix에서는 없는 숫자가 됩니다.

Thread.MAX_PRORITY로 설정하면 JVM이 알아서 WINDOWS에서 10 UNIX에서는 7로 설정을 합니다.

자바가 모든 운영체제에서 동작하는 애플리케이션을 한 번만 제작해도 되는 이유는 JAVA의 옵션들을 사용한다면 값은 JVM이 운영체제 별로 알아서 할당을 합니다.

JDK(개발도구) 자체는 운영체제 별로 분류가 되어 있지 않지만 실행을 해주는 JVM이 운영체제 별로 별도로 존재해서 JVM이 알아서 옵션 값들을 설정합니다.

=>fIELD Summary는 메소드들에서 사용하기 위한 옵션 값들입니다.

 

 

만개 정도 scrapping할 경우 thread를 이용하면 빨리 할 수 있다.

mmo rpgthread

게임에스 client쪽은 스레드

서버는 프레임을 사용하기 때문에 보통은 대신해준다.

웹프로그램밍에서  was가 알아서 thread만들어준다.

 

 

//class 만드는 경우는 대부분 인스턴스를 2 이상 만드는 경우

class Threadext extends Thread{

       public void run() {

               //스레드 자신의 이름을 10 출력(1초만다 쉬면서)

               for (int i = 0; i < 10; i++) {

                      try {

                             Thread.sleep(1000);

                             System.out.println(getName());

                      } catch (InterruptedException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                      }

               }

       }

}

 

public class Main4 {

 

       public static void main(String[] args) {

               //정수이다.

               //System.out.println(Thread.MAX_PRIORITY);//10

               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.thread 강제 종료

=>thread를 강제로 종료할 때는 스레드 인스턴스가 interrupt()라는 메소드를 호출해주면 되는데 스레드클래스의 run메소드에 interruptException이 발생했을 때 run메소드를 종료하도록 코드를 만들어주어야 합니다.

thread를 강제로 종료하고 싶을때

전투를 걸어놓고 중지 못하게 할 경우 특정한 thread는 작업이 끝날 떄 까지 종료안되게 할 때가 있다.

 

=>Threadext클래스에서 catch구문에서 return 을 생략하고 실행해보고 rerurn을 넣고 실행

두번째 스레드의 이름인 thread-1이 계속 출력되기도 하고 3초 후에 출력이 안되기도 합니다.

return 이 있고 없고에 따라서 스레드가 강제로 종료되기도 하고 그렇지 않기도 합니다.

//class 만드는 경우는 대부분 인스턴스를 2 이상 만드는 경우

class Threadext extends Thread{

       public void run() {

               //스레드 자신의 이름을 10 출력(1초만다 쉬면서)

               for (int i = 0; i < 10; i++) {

                      try {

                             Thread.sleep(1000);

                             System.out.println(getName());

                      }

                      //InterruptedException 발생했을 return 하도록 만들어주면 스레드가 강제로

                      //종료 있습니다.

                      catch (InterruptedException e) {

                             // TODO Auto-generated catch block

                             //e.printStackTrace();

                             //중지하게 하려면 interrupt신호를 보낸다.

                             //스마트 전화올 경우

                             return; //interrup할때 1번은 안나온다.

                      }

               }

       }

}

 

public class Main4 {

 

       public static void main(String[] args) {

               //정수이다.

               //System.out.println(Thread.MAX_PRIORITY);//10

               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스레드에게 interrupt 발생시킨것이다 하지만 중지가 안된다.

                      th2.interrupt();

               }catch(Exception e) {

                     

               }

       }

 

}

 

10.Thread 실행 제어

void join(int millis, int nanos) :입력한 시간동안만 스레드를 수행

윈도우즈와 같은 클라이언트 운영체제에서는 1/20 이항의 설정은 의미가 없습니다.

원도우즈는 nanos 아무런 의미가 없다. 무의미하다.

클라이언트에서는 1초에 50 정도가 maximum이다.

 

void suspend() :작업을 일시 정지 (wait)

void resume():  일시 정지된 스레드가 작업을 계속

 

void yield():실행 상태를 양보하고 대기 상태로 전환

 

 

 

*종료안되게 할 경우 :

keyboard Interrupt

 

11.ThreadGroup

=>Thread를 묶어서 관리하기 위한 클래스

=> 몇 몇 메소드가 특정 운영체제에서 제대로 동작하지 않아서 비추천

=>List등을 이용해서 그룹화하기를 권장

 

 

Multi Thread 고려사항

=>2개 이상의 스레드가 실행중인 경우를 multi thread

1.long 의 문제

=>32bit 시스템에서 64bit 자료형인 long을 사용하면 부분수정 문제가 발생할 수 있음

 

 

 

실행 하고 정보를 제어블록에 저장한다.

스레드를 바꿀때 현재 상태 저장하고 th2제어블록 읽는다.

스레드 바꿀때 th2제어블록에 저장한다음 th1의 제어블록 을 읽고 실행한다.

 

정보를 저장하고 읽는 것을 context switching

=>스레드의 개수가 너무 많거나 짧은 시간 단위로 작업하면 일하는 시간보다 읽는 시간이 길어지면 over head(conext switch -문맥 교환) 가 많이 발생해서 효율이 떨어진다.

 

정말 특별한 경우가 아니면 공유변수 global variable 만들지 말라 ?

static변수를 만드는 것을 좀 금지 하면 좋다.signle ton

싱글톤 패턴

애플리케이션이 시작될 때 어떤 클래스가 최초 한번만 메모리를 할당하고(Static) 그 메모리에 인스턴스를 만들어 사용하는 디자인패턴.

Critical Section(임계 영역) : 공유자원을 사용하는 코드 영역

3.공유자원 문제

1) 수정중인 공유자원을 다른 스레드가 수정하는 경우

i라는 데이터가 있다.0에서 출발할 것이다.

 

 

thread동시에 돌릴 경우 이상한 값이 나올 수 있다.

이론적으로 는 1부터 200까지 나와야 하는데

total 200가지 합계가 나와야 한다.

약간의 dealy를 발생하면

i = 0  sum = 0 A

더하기 전에 다른 스레드가 사용해버리면 이상한 결과가 나올 수 있다.

 

 

은행에서 잔액이 10000 , 10000을 찾으려고 할 경우 atml기계에서 5000원 찾을 경우 10000을 찾을 수 없다. 다른데서 수정해 버렸기 때문에

읽는데는 문제가 안된다. 수정시 문제가 생긴다.

=>하나의 수정이 종료되고 다른곳에서 사용해야 한다.  동기화(Synchronized)

a가 끝날 때 까지 B가 기다려야 한다.

=>mutual Exclusion(상호 배제 ) ->lock으로 해결

2). 생산자와 소비자 문제

=>작업순서의 문제

공장자동화 로봇으로 만들 경우

진열대를 공유한다.

A   가 진열대에 물건 올리면  B가 처리한다.

진열대 공유

동시에 해도 된다.

 

 

 

 

a가 물건을 생산해주면 b가 처리한다.

A가 물건을 쌓기만하고 B가 처리안할 떄 > 적체

A가 안했는데 B가 하려고 할때 ->문제가 생긴다.

 

=>생산자가 생산하면 소비자는 작업을 수행해야 한다.

구현 방법 : 끝났는지 안 끝났는지 계속 쳐다본다. 이 방법은 별로 안좋아서 signal줬으면

wait(소비자) notify(생산자)

 

카톡 등은 udp이다. 안받을 수 있다.

정확하게 메시지 보내야한다.

 

signal두개 있다. notify(하나만) ,notifyAll (전체 일어나는 것)

 

3) dead lock

=>결코 발생할 수 없는 사건을 무한정 기다리는 것

A

B

 

x1(A소유)

x2(B소유)

A,B

A,B

 

x1 B가 필요하는데 x2가 안줄려고한다.

x2A가 필요하는데 x1가 안줄려고한다.

synchronized를 잘못 줘서 문제가 생긴다.

양쪽 다 synchronize를 주는 것은 문제가 생긴다.

 

1차선인데 양쪽 오는 경우 서로 양보 안하는 것

 

4.Semaphore ->CLASS이름

=>공유자원 여러개

화장실이 3개가 있을 경우  동시에 3명 가능하다.

A가 들어갔다.

B가 들어갔다.

C가 들어갔다.

D가 왔는데 3개 노크해봐야 한다. 다 찼을 경우

 

 

 

 

DA뒤에 서고 Eb뒤에 섰을 경우 B가 먼저 나오면 문제가 생긴다.

 

그래서 밖에 현광판을 새운다.

3 -> 2 -> 1 ->0

0일 경우 빈자리가 없어서 기다린다.

공유자원이 여러개 일때 관리가 편하게 할 때

 

VISUAL c는 이름이 같게 되여있다.

 

 

 

 

 

Properties

반응형

'Study > Java' 카테고리의 다른 글

java-13  (0) 2020.10.03
java-12  (0) 2020.10.02
java-10  (0) 2020.09.30
java-9  (0) 2020.09.29
java-8  (0) 2020.09.28

+ Recent posts