금일 수업 내용 : Thread
package com.poseidon.thread;
// 24-01-03
// 남은 것 : Thread, IO, Net, GUI
// 이후, 프로젝트 제작 (Java, DB 중 택)
/*
* 프로세스 : 운영체제에서는 실행 중인 하나의 어플리케이션을 프로세스라고 함
* 사용자가 애플리케이션을 실행하면 운영체제로부터 실행에 필요한 메모리를 할당받아
* 애플리케이션의 코드를 실행하는 것이 프로세스
* 스레드 : 운영체제는 두가지 이상의 작업을 동시에 처리하는 멀티 태스킹을 할 수 있도록
* CPU 및 메모리 자원을 프로세스마다 적잘히 할당하고 병렬로 실행
*
* 스레드 생성과 실행
* 1. Runnable 인터페이스를 구현하는 방법
*
* 2. Thread 클래스를 상속받는 방법
*
* 두가지 방법인 이유
* - 다른 클래스가 상속 중인 경우 Thread 클래스를 상속받지 못함. 이런 경우를 대비하여
* 인터페이스 Runnable 이 만들어져 있음 (Thread 클래스를 상속하는게 편함)
*
* 실행은 start() 로 실행
*/
public class ThreadEx extends Thread{ // Thread 클래스 상속
@Override
public void run() {
System.out.println("Thread 시작");
}
public static void main(String[] args) {
ThreadEx th01 = new ThreadEx(); // 객체 생성
th01.start(); // Thread 는 start() 로 실행
}
}
여러 개의 Thread 실행해보기
package com.poseidon.thread;
public class Thread02 extends Thread{
int seq;
public Thread02(int seq) {
this.seq = seq;
}
@Override
public void run() {
System.out.println(this.seq + " Thread 시작");
try { // sleep 은 오류가 발생할 수 있어 try/catch 해야 함
Thread.sleep(1000); // = 1000 밀리초 = 1 초
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.seq + " Thread 종료");
}
public static void main(String[] args) {
System.out.println("main 메소드 시작");
for (int i = 0; i < 3; i++) {
Thread02 th02 = new Thread02(i);
th02.start();
}
System.out.println("main 메소드 종료");
}
}
실행 결과
Join 사용해보기
package com.poseidon.thread;
import java.util.ArrayList;
import java.util.List;
public class Thread03 extends Thread {
int seq;
public Thread03(int seq) {
this.seq = seq;
}
@Override
public void run() {
System.out.println(this.seq + " Thread 시작");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.seq + " Thread 종료");
}
public static void main(String[] args) {
System.out.println("main 시작");
List<Thread> tList = new ArrayList<Thread>();
for (int i = 0; i < 3; i++) {
Thread03 th03 = new Thread03(i);
th03.start();
tList.add(th03);
}
for (Thread thread : tList) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main 종료");
}
}
실행 결과 :
Runnable 인터페이스를 구현하여 만들기
package com.poseidon.thread;
import java.util.ArrayList;
class A {
}
// 다른 클래스를 상속하여 Thread 를 상속하지 못할 때 사용
public class Thread04 extends A implements Runnable {
int seq;
public Thread04(int seq) {
this.seq = seq;
}
@Override
public void run() {
System.out.println(this.seq + " Thread 시작");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.seq + " Thread 종료");
}
public static void main(String[] args) {
System.out.println("main 실행");
ArrayList<Thread> tList = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new Thread04(i));
// t 의 생성자로 Runnable 을 구현한 객체를 넘김
t.start();
tList.add(t);
}
for (int i = 0; i < tList.size(); i++) {
Thread t = tList.get(i);
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main 종료");
}
}
Queue 와 Stack
package com.poseidon.coll;
import java.util.Stack;
/*
* 선입선출 First In, First Out : FIFO / ex) 프린터 사용
* 후입선출 Last In, First Out : LIFO / ex) 인터넷 앞으로 가기, 뒤로 가기
*/
class Coin {
private int value;
public Coin(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public class Stack01 {
public static void main(String[] args) {
Stack<Coin> coinBox = new Stack<Coin>();
coinBox.push(new Coin(100));
coinBox.push(new Coin(50));
coinBox.push(new Coin(500));
coinBox.push(new Coin(10));
while(!coinBox.isEmpty()) {
Coin coin = coinBox.pop();
System.out.println("동전 : " + coin.getValue());
}
}
}
Queue
package com.poseidon.coll;
import java.util.LinkedList;
import java.util.Queue;
class Message {
public String command;
public String to;
public Message(String command, String to) {
this.command = command;
this.to = to;
}
}
public class Queue01 {
public static void main(String[] args) {
Queue<Message> messageQueue = new LinkedList<>();
messageQueue.offer(new Message("sendMail", "홍길동"));
messageQueue.offer(new Message("sendSMS", "김길동"));
messageQueue.offer(new Message("sendKaKaoTalk", "최길동"));
while (!messageQueue.isEmpty()) {
Message message = messageQueue.poll(); // 큐에서 1 개씩 꺼냄
switch (message.command) {
case "sendMail":
System.out.println(message.to + "님께 메일을 보냅니다");
break;
case "sendSMS":
System.out.println(message.to + "님께 문자를 보냅니다");
break;
case "sendKaKaoTalk":
System.out.println(message.to + "님께 카카오톡을 보냅니다");
break;
}
}
}
}
Input, Output
package com.poseidon.io;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class IO01 {
public static void main(String[] args) throws Exception {
OutputStream os = new FileOutputStream("c:/temp/test.txt");
byte a = 97;
byte b = 98;
byte c = 99;
os.write(a);
os.write(b);
os.write(c); // ASCII CODE 로 값 전달
os.flush(); // abc 출력
os.close();
}
}
배열을 담아 보내기
package com.poseidon.io;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class IO02 {
public static void main(String[] args) throws Exception{
OutputStream os = new FileOutputStream("c:/temp/test2.txt");
byte[] arr = new byte[] {66, 69, 72, 72, 79};
// 1byte = 8bit
os.write(arr);
os.flush(); // BEHHO 전송
os.close();
}
}
파일 읽기
package com.poseidon.io;
import java.io.FileInputStream;
import java.io.InputStream;
public class IO03 {
public static void main(String[] args) throws Exception{
InputStream is = new FileInputStream("c:/temp/test.txt");
// abc 가 들어있는 문서 파일
while (true) {
int data = is.read(); // 출력할 값이 없으면 -1 대입
if (data == -1) {
break;
}
System.out.println(data);
}
is.close();
}
}
파일 읽기 두번째
package com.poseidon.io;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
public class IO04 {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("c:/temp/test.txt");
// abc 가 들어있는 txt 파일
byte[] arr = new byte[2];
while (true) {
int readByteNum = is.read(arr);
// .read() : 읽은 메소드 개수 반환
if (readByteNum == -1) { // 읽을 게 없으면 -1
break;
}
for (int i = 0; i < readByteNum; i++) {
System.out.println((char) arr[i]);
} // 메모장에 적힌 값을 ascii code 로 입력받는데, 그걸 다시 문자로 변환
System.out.println(Arrays.toString(arr));
System.out.println(readByteNum + " : " + Arrays.toString(arr));
}
is.close();
}
}
문자열 저장하기
package com.poseidon.io;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class IO05 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("c:/temp/test5.txt");
Writer writer = new OutputStreamWriter(fos);
// Writer writer = new OutputStreamWriter(new FileOutputStream("c:/temp/test6.txt"));
writer.write("문자열을 저장합니다.");
writer.flush();
writer.close();
}
}
어느 디렉토리에 들어있는 파일 형태와 정보 확인하기
package com.poseidon.io;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class IO06 {
public static void main(String[] args) {
File dir = new File("c:/temp/images");
if (dir.exists() == false) {
dir.mkdir(); // 새로운 폴더를 생성
// dir.mkdirs() : 경로상에 없는 모든 폴더를 생성
// createNewFile() : 새로운 파일을 생성
}
File temp = new File("c:/temp");
File contents[] = temp.listFiles();
System.out.println(Arrays.toString(contents));
System.out.println("시간\t\t\t형태\t\t크기\t이름");
System.out.println("----------------------------------------------------");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a HH:mm");
for (File file : contents) {
System.out.print(sdf.format(new Date(file.lastModified())));
if(file.isDirectory()) {
System.out.println("\t<DIR>\t\t\t" + file.getName());
} else {
System.out.println("\t\t\t" + file.length() + "\t" + file.getName());
}
// System.out.println();
}
}
}
Inner 클래스
헷갈리긴 하지만..
package com.poseidon.inner;
// 중첩 클래스 : 클래스 속 클래스
/* Inner Class 내부 클래스
* 클래스 내부에 선언된 클래스 : 두 클래스가 서로 긴밀한 관계
*
* 장점
* 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있음
* 캡슐화, 코드의 복잡성을 줄여줌
*
* 보통의 클래스
* class A{}
* class B{}
*
* 내부 클래스는 두 클래스가 긴밀하고, 내부 클래스는 잘 사용되지 않는 것
* class A { class B {} }
*
* 종류
* static(정적) 클래스 : 외부 클래스의 멤버 변수 위치에 선언, 외부 클래스의 스태틱 멤버처럼 다뤄짐
* 주로 외부 클래스의 스태틱 멤버, 특히 스태틱 메소드에서 사용 할 목적으로 선언
*
* 멤버 클래스 : 외부 클래스의 멤버 변수 위치에 선, 외부 클래스의 인스턴스 멤버처럼 사용
* 주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 활용
*
* 지역 클래스 : 외부 클래스의 메소드나 초기화 블럭 안에서 선언, 선언된 영역 내부에서만 사용 가능
*
* 익명 클래스 : 클래스 선언과 객체 생성을 동시에 하는 이름이 없는 클래스(일회용)
*/
class A {
public A() {
System.out.println("A 객체가 생성됨");
}
class B {
int field1;
// static int field2; static 사용 X
public B() {
System.out.println("B 객체가 생성됨");
}
public void methodB() { }
// public static void methodB2() {} static 사용 X
}
static class C { // 정적 멤버 클래스
int field1;
static int field2;
public C() {System.out.println("C 객체가 생성됨");}
public void methodC() {}
public static void methodC2() {}
}
public void methodA() { // class A 의 메소드
// 로컬 영역
int num = 10; // 지역 변수
class D { // 지역 클래스
int field1;
public D() {
System.out.println("D 객체가 생성됨");
}
public void methodD() {}
// public static void methodD2() {} static 사용 X
} // Class D 의 마지막
D d = new D(); // 객체 생성
d.field1 = 3;
d.methodD(); // D 객체의 필드 및 메소드 접근 가능
} // methodA 의 마지막
}
public class Inner01 {
public static void main(String[] args) {
A a = new A();
A.B b = a.new B();
b.field1 = 1;
b.methodB();
A.C c = new A.C();
c.field1 = 1;
A.C.field2 = 2; // static
c.methodC();
A.C.methodC2(); // static
a.methodA(); // 메소드가 실행되며 D 객체 생성됨
}
}
2번 Inner 와 3번 Inner 가 왔다갔다 함
package com.poseidon.inner;
class Button {
OnClickListener listener;
void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
void touch() {
listener.onClick();
}
static interface OnClickListener {
void onClick();
}
}
public class Inner02 implements Button.OnClickListener{
@Override
public void onClick() {
}
public static void main(String[] args) {
}
}
package com.poseidon.inner;
public class Inner03 {
public static void main(String[] args) {
Button button = new Button();
button.setOnClickListener(new Inner02());
button.touch();
}
}
클래스의 메소드를 사용할 곳에서만 오버라이드하여 사용하기
package com.poseidon.inner;
/*
* 클래스 명이 없는 클래스, 선언과 동시에 인스턴스 생성을 하나로 통합한 클래스
* 클래스를 인수값으로 사용하는 클래스, 객체를 한 번만 사용할 경우 사용
*
* 클래스의 선언부가 없기 때문에 이름이 없음 = 생성자를 가질 수 없음
* 슈퍼 클래스의 이름이나 구현할 인터페이스를 구현하거나 둘 이상의 인터페이스를 구현할 수 없음
* 오직 하나의 클래스를 상속받거나 하나의 인터페이스만 구현 가능
*
* 코드 블럭에 클래스를 선언하는 점만 제외하고는 생성자를 호출하는 것과 동일
* 객체를 구성하는 new 문장 뒤에 클래스의 블록 {}, 메소드를 구현한 블록이 있고 블록 끝 세미콜론이 붙음
* new 뒤에 오는 생성자명이 기존 클래스명이면 익명 클래스, 자동으로 클래스의 하위 클래스가 됨
*
* 인터페이스인 경우에 인터페이스를 상속하는 부모 클래스가 Object가 됨
*/
class Anonymous {
public void print() {
System.out.println("출력");
}
}
public class Inner04 {
public static void main(String[] args) {
Anonymous any = new Anonymous() {
@Override
public void print() {
System.out.println("프린트");
}
};
any.print(); // "프린트" 출력
}
}
'JAVA' 카테고리의 다른 글
240216 JAVA 옵셔널 공부하기 (0) | 2024.02.16 |
---|---|
240111 홈페이지 만들기 (2) | 2024.01.11 |
231227 Java (0) | 2023.12.27 |
231226 Java (0) | 2023.12.26 |
231222 Java (0) | 2023.12.22 |