| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 바인딩변수
- c:if
- Java
- 유효성검사
- .xml
- frontController
- gradle
- 어노테이션
- after-throwing
- produces
- application.properties
- PointCut
- MVC
- @RequestMapping
- 생성자주입
- @RequestParam
- AOP
- 서비스레이어
- 스프링
- spring
- @ResponseBody
- springjdbc
- 비즈니스레이어
- springmvc
- 의존주입
- SpringBoot
- Model
- @
- @Valid
- jointpoint
- Today
- Total
메모장
스레드(Thread) 와 파일 입출력 본문
스레드 ( Thread )
[ 스레드 Thread ]
메모리를 할당받은 프로세스 (실행중인 프로그램) 에서
실질적인 작업을 수행하는 주체이다 ! - 우리 모두 개개인의 하나의 스레드 라고 생각해도 된다.
ex ) 쇼핑몰을 이용하는 고객 한명한명이 스레드 라고 생각 한다.
만약 재고가 5개 남은 상품이 있었을때
t1 (사용자1) -> 장바구니에 3개를 담았고
t2 (사용자2) -> 5개를 즉시 구매했다.
이랬을시 t1은 장바구니에만 담아놨고 실제로 물건은 t2에게 간다
// 따라서 현재 데이터가 어떤 상태인지가 중요하다.
※ 동기화 : // ex ) 동기화 하는것 -> 계좌 나 티켓팅
ex ) 동기화 안하는 것 - > 장바구니 // 장바구니에 담는다고 딴사람을 막을순 없다
// 스레드는 독립적으로 일하는 일원이기 때문에
// 공유자원을 어떤 스레드가 점유하고 있을때 ,
// 다른 스레드의 접근을 막아줘야 한다.
그렇다면 위 내용 중 프로세스는 무엇인가 ? 실행중인 프로그램 만 !! 보인다.
프로그램 --실행상태--> 프로세스
일(동작)할수있게 메모리(자원)를 할당받은 상태
프로세스가 진행되는 방식에 대해서도 알아보자 !
▶ 프로세스가 실행되는 방식
- 선점형 방식 : 우선순위 순서대로 자원(메모리)을 할당받아 진행되는 방식 -> 기아현상(자원을 할당받지 못한다.)이 발생될 가능성이 있음 // 예전에 쓰던 방식
ex ) A 3개 B 1개 C 2개 라고 가정하고 A가 우선순위가 제일 높다고 했을때
우선순위 부터 쭉쭉쭉 실행되는데 우선순위가 낮은 c는 계속 대기하다가 본인 우선순위보다 높으면 알파벳이 들어오면 또 앞으로 나간다. 그래서 오래 기다리다가 실행 못할수 있음.
- 시간분할 방식 : 시간을 동일하게 배분하여 골고루 실행될 수 있도록 진행하는 방식 -> 기존의 선점형 방식에서 우선순위가 낮아 오-래 기다린 프로세스의 우선순위를 높여주는 방식
=> OS(운영체제)의 '스케줄러' (프로세스를 어떤 방식으로 실행시키는지 방식 이다 )
package class01;
// [스레드 Thread]
// 이미 JAVA에서 구현한 Thread 클래스를 가져다가 사용
// 코드를 재사용할 예정
// => 상속
class Th01 extends Thread{
@Override
public void run() {
for (int i = 1; i < 10; i++) {
System.out.println("Thread 01 " + i);
}
}
}
class Th02 extends Thread{
// 이슈가 안났으면 ? 기본생성자가 이미 숨어있구나 ?
@Override
public void run() { // Thread에 핵심이 되는 메서드
for (int i = 1; i < 10; i++) {
System.out.println("Thread 02 " + i);
}
}
}
public class Test01 {
public static void main(String[] args) {
Th01 t1 = new Th01(); // 생성
// 생성이 되면 , 즉시 대기상태가 됨
Th02 t2 = new Th02();
// 쇼핑몰을 이용하는 고객 하나하나가 스레드 라고 생각
// 수행
t1.start(); // 스레드 객체야, 일해 ! // 너 일해 켜놓고
t2.start(); // -> run()메서드를 실행시킴 // 너도 일해
// 스레드 객체들은 현재 독립적으로 일을 수행하고 있구나! --> 요것만 이해하면 됨
// start()로 인해 run()을 수행하게 되고, 주어진 run()을 수행하게 되면
// 데드 상태가 됨
// 가지고 있던 메모리를 다 해제 해지 한다. 자기가 점유하고 있던 메모리를
// 다시 돌려준다.
// 스레드 생명주기(라이프 사이클)
// 생성 -> 대기 -> 수행 -> 데드
// 블록 : 자원(메모리)을 할당받지 못하도록 막아둔 상태
// 대표적인 스레드 블록상태 : sleep
for(int i=1;i<=10;i++) {
System.out.println(i);
try {
Thread.sleep(1000); // 1000 == 1초
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
예시 ) 티켓을 구매하려는 세 사람
package class01;
// ex ) 동기화 하는것 -> 계좌 나 티켓팅
// 동기화 : ex ) 동기화 안하는 것 - > 장바구니 // 장바구니에 담는다고 딴사람 막을순 없다
// 스레드는 독립적으로 일하는 일원이기 때문에
// 공유자원을 어떤 스레드가 점유하고 있을때 ,
// 다른 스레드의 접근을 막아줘야 한다.
class Person extends Thread{
//thread.start() - > run()메서드가 수행
Ticketting t=new Ticketting(); // 객체 선언이 지금 중요한 부분이 아니라 일단 선언
@Override
public void run() {
t.pay();
}
}
class Ticketting { // Person 객체들이 사람들이 공유자원인 티켓을 구해하는 로직
static int ticket = 2; // 공유 자원 매표소 같은곳
// 공유자원, 클래스 변수 // 누구든지 사간다면 티켓이 있는지 없는지 봐야한다.
synchronized void pay() { // 공유자원을 건드리는 얘가 문제다
if(ticket>0) {
System.out.println(Thread.currentThread().getName()+"구매성공!");
ticket--; // get으로 받았으므로 private 이다
}
else {
System.out.println(Thread.currentThread().getName()+"구매실패ㅠㅠ...");
}
System.out.println("남은티켓: "+ticket);
}
}
public class Test02 {
public static void main(String[] args) {
Person p = new Person(); // 스레드를 상속받은
Thread t1=new Thread(p,"홍길동");
Thread t2=new Thread(p,"코난");
Thread t3=new Thread(p,"짱구");
t1.start();
t2.start();
t3.start();
// 각각의 일을 할수 있는 스레드를 만들었다
//홍길동이 티켓을 보았을땐 2개 코난이 티켓을 봤을땐 두개
//짱구가 봤을땐 1개 여서 또 구매
// 사람의 이름을 멤버변수로 선언 한적이 없어서 스레드에 이름을 부여해줌
}
}
파일 입출력
[파일입출력]
파일 : 사진, 영상, 음성파일, 엑셀, 문서, 텍스트문서,... // 파일의 종류들
웹에서는 사진 파일
java에서는 .txt 로 실습할 예정
C:\HONG\resource // 저장할 곳
package class04;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
// 지금까지는 콘솔이랑 자바랑 대화 시켰지만
// 운영체제(컴퓨터)랑 자바랑 대화를 시킬 예정
public class Test01 {
public static void main(String[] args) {
// ▶ 1. 파일 생성하기 // 기본생성자가 없다 // 우리가 경로를 작성해줘야 한다.
File file = new File("C:\\HONG\\resource\\test.txt"); // 파일 기본 생성자가 없어
// 파일에게는 default 생성자가 없다
// 해당파일이 존재하지 않으면, 하나 새로 생성해준다 ! <- 이런뜻
try {
file.createNewFile();
} catch (IOException e) { // IO 랑 관련된것은 항상 try catch를 해줘야 한다.
// TODO Auto-generated catch block
e.printStackTrace();
} finally { // 마무리로 확인해주기
System.out.println("파일 객체생성 완료 !");
}
// ▶ 2. 파일 읽어오기
try {
FileInputStream fis = new FileInputStream("C:\\HONG\\resource\\test.txt");
// FileInputStream fis = new FileInputStream(file);
// 내가 뭐라고 썼는지 몇번 읽어와야되는지 뭔지 몰라 while
int data; // 얘가 반환을 int 로 하는 바람에
while ((data = fis.read()) != -1) {
// 읽어온 데이터가 -1 이면 "다 읽었다."
// c언어는 마지막 끝나면 end of file이라 하는데
// 자바는 int 라서 -1이면 다 읽었다고 표현한다
System.out.println((char) data);
}
System.out.println();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally { // 마무리로 확인해주기
System.out.println("fis객체로 파일 읽어오기 작업 완료!");
}
// ▶ 3. 파일 작성하기
try {
FileOutputStream fos = new FileOutputStream("C:\\HONG\\resource\\test.txt", true);
// 생성자에 작성한 파일이 존재하지 않으면 새로 생성 해주고
// 파일이 존재하면 !!! 덮어 쓰기 !!! 된다.
// 파일이 존재할때 이어쓰기 하고 싶으면 ? (, true) 두번째 인자에 true를 쓰면 된다.
// 얘네가 문자로 소통하는게 아니라 정수로 소통한다.
fos.write(65); // 'A'
fos.write(97); // 'a' -> 아스키 코드
// ★★★★★★★
// OS와 소통하던 통로를 직접 닫아주지 않으면 다음 수행시 문제가 발생할 수도 있다.
fos.flush();
fos.close();
// 안닫았을시 문제가 생기는 애들 ! 꼭 닫아줘야함
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("fos객체로 파일 작성하기 작업 완료!");
}
}
}
[예제 문제 1]
D:\HONG\resource\test01.txt 파일이 있습니다.
정수가 1개 작성되어있습니다.
ex) 2 => 12
입력되어있는 정수는 짝(홀)수입니다.
// 1. 파일 생성하기
File file = new File("C:\\HONG\\resource\\test.txt");
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("파일 객체생성 완료!");
}
// 2. 파일 읽어오기
String a = "";
try {
FileInputStream fis = new FileInputStream("C:\\HONG\\resource\\test01.txt");
int data;
try {
while ((data = fis.read()) != -1) {
System.out.print((char) data);
if (data % 2 == 1) {
a = "홀";
} else {
a = "짝";
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
System.out.println();
System.out.println("입력하신 수는 " + a + "수 입니다.");
}
// 강사님 코드와 비교
// "유지보수 용이"
final String path_START="D:\\KIM\\resource\\"; // 선언부에 선언해주기
final String path_FILE01="test01";
final String path_FILE02="test02";
final String path_END=".txt";
try { // 파일 읽어오기
FileInputStream fis=new FileInputStream(path_START+path_FILE01+path_END);
int data; // 변수 설정
String num=""; // 문자열 변수
while( (data=fis.read()) != -1 ) { // -1이 되면 다 읽은 뜻으로 -1이 되지않을때 까지 반복
num+=(char)data; // data를 형변환 해서 num에 " " 로 연결해서 담는다.
}
System.out.println(num);
data=Integer.parseInt(num); // 정수로 바꾸기
System.out.println(data);
if(data%2==0) { // data가 짝수 일때
System.out.println("짝수");
}
else { // 아닐때
System.out.println("홀수");
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("fis객체로 파일 읽어오기 작업 완료!");
}
[문제 2]
D:\HONG\resource\test02.txt 파일이 있습니다.
아무내용도 작성되어있지않습니다.
abcde...xyz까지 작성해주세요!~~
// 1. 파일 생성하기
File file2 = new File("C:\\HONG\\resource\\test02.txt");
try {
file2.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("파일 객체 생성 완료 !");
}
// 3. 파일 작성하기
try {
FileOutputStream fos = new FileOutputStream("C:\\HONG\\resource\\test02.txt");
// FileOutputStream fos=new FileOutputStream(path_START+path_FILE02+path_END);
// 강사님 풀이 // 이 부분 말고는 비슷하다.
int result = 0;
for (int i = 97; i <= 122; i++) { // 아스키 코드
result = i;
fos.write((char) result);
}
fos.flush();
fos.close(); // 꼭 닫아주기
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("fos객체로 파일 작성하기 작업 완료 !");
}
package class04;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test04 {
public static void main(String[] args) {
// ▶ 4. 사진 복사하기
final String path="C:\\\\HONG\\\\resource\\\\";
final String fileName="짱구.jpg";
final String fileCopy="짱구 - 복사본.jpg";
try {
FileInputStream fis=new FileInputStream(path+fileName); // 파일 읽어오기
FileOutputStream fos=new FileOutputStream(path+fileCopy); // 파일 작성하기
int data;
byte[] buff=new byte[10000]; // 10000 byte 씩 받는다
while((data=fis.read(buff))!=-1) { //-1로 종료되기 전까지
// 0 부터 data 까지 만큼 버퍼배열로 풀어
/////System.out.println("확인");
fos.write(buff, 0, data); //버퍼배열, 0 시작부터 , 끝 data 까지
}
fos.flush();
fos.close(); // 꼭 닫아주기
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("사진 실습 완료!");
}
}
}
'JAVA > 개념정리' 카테고리의 다른 글
| MVC 패턴 중 Model 공부 (0) | 2024.04.07 |
|---|---|
| MVC 패턴 (0) | 2024.04.07 |
| 예외 와 예외처리 (0) | 2024.04.07 |
| 컬렉션 프레임 워크 (0) | 2024.04.06 |
| 객체배열 (1) | 2024.04.06 |