// 클래스 : 객체를 추상화 해놓은 것
class Npc
{
// 필드 : 데이터
String name;
int hp;
// 메서드 : 동작(기능)
void say()
{
System.out.println("안녕하세요");
}
}
public class NpcUse
{
public static void main(String[] args) {
// 클래스를 이용해 객체 생성
// Npc라는 설걔도(클래스) 이용해 Npc 객체 생성
// 클래스 타입의 변수는 new를 통해 객체 생성
// 클래스 타입의 참조 변수는 스택, 생성된 객체는 힙에 적재
Npc saram1 = new Npc();
// 필드 접근
saram1.name = '경비'; // 멤버 변수에 직접 접근
saram1.hp = 100;
System.out.println(saram1.name + ":" + saram1.hp);
// 메서드 호출
saram1.say();
}
}
3) 객체와 클래스
클래스 타입
변수
= 객체 생성
생성자
java 파일명
으로 java.exe 실행 ➡️ JVM 만들고 파일명 클래스를 찾아 main() 실행)4) 오버로딩 (overloading)
class Calc
{
int add(int a, int b)
{
return a + b;
}
int add(int a)
{
return a + 1;
}
double add(double a, double b)
{
return a + b;
}
}
public class OverloadingUse
{
public static void main(String[] args)
{
Calc calc = new Calc();
int nRtn1 = calc.add(3, 9);
int nRtn2 = calc.add(3);
double nRtn3 = calc.add(3.0, 9.0);
System.out.println("Rtn1 = " + nRtn1);
System.out.println("Rtn2 = " + nRtn2);
System.out.println("Rtn3 = " + nRtn3);
}
5) 생성자
6) 접근 제한자
class Student1
{
String name;
int age;
}
class Stuedent2
{
public String name;
private int age; // private 멤버 변수
public Student2(String name, int age)
{
this.name = name; // 멤버변수와 매개변수명이 겹침
this.age = age;
}
public int getAge() // 게터 (값 가져오는 메서드
{
return age;
}
public void setAge() // 세터 (변수에 값을 대입하는 메서드)
{
if (age < 0 || age > 150) // 유효성 검사
{
System.out.println("나이가 부적절합니다");
this.age = 0;
return;
}
this.age = age;
}
}
public class PrivateUse
{
public static void main(String[] args)
{
Student1 student1 = new Student1();
student1.name = "김수현"; // 멤버 변수 직접 접근
student1.age = -20;
Student2 student2 = new Student2("김수현", 20);
student2.name = "손오공";
// student2.age = -10; // 에러 발생
student2.setAge(10);
int age = student2.getAge();
}
}
📖 참고 📖 가비지 컬렉션
- 수행하는 동안에는 모든 스레드가 멈춤
- 실행 타이밍은 시스템의 성능에 영향을 미치지 않도록 별도의 알고리즘으로 실행됨
- 가비지 컬렉션 발생하면, 소멸 대상이 되는 인스턴스가 결정되지만 바로 소멸X
- 종료가 되면 객체는 운영체제에 의해 소멸됨
- 반드시 객체 소멸하기 원한다면 finalize() 메서드 호출
- 실행 :
System.gc();
- 객체 소멸 :
System.runFinallization();
1) 스태틱
2) 전역 변수로 사용
class Cat {
static int a = 5; // 스태틱 변수 (전역 변수)
int num = 3; // 인스턴스 변수
void printValue(int num) {
this.num = num;
System.out.println("num : " + this.num);
System.out.println("a : " + a);
}
}
public class Ex01{
public static void main(String[] args) {
int num = 2;
Cat cat1 = new Cat(); // cat1 변수 - 스택, Cat클래스형 객체 - 힙에 생성
cat1.num = 5; // 힙 영역에 생성된 객체 안에 존재
cat1.a = 10; // static 영역
}
}
3) main보다 먼저 실행
4) 유틸 메서드로 사용
public calss MyCalculator
{
public static int add(int n1, int n2)
{
return n1 + n2;
}
}
public class Ex {
public static void main(Stiring[] args)
{
MyCalculator calc1= new MyCalculator(); // 객체 생성 후 사용
int num1 = calc1.add(1, 2);
int num2 = MyCalculator.add(2,3); // 새로 객체 생성하지 않고 사용
}
}
class 자식 클래스 extends 부모 클래스
{
}
📖 참고 📖 자바의 다중 상속
- 여러 클래스를 동시에 상속하는 다중 상속 지원X (단계별 상속 사용)
- 2개 이상의 상위 클래스에 같은 이름의 메서드가 정의되어 있다면, 다중 상속을 받는 하위 클래스는 어떤 클래스의 메서드를 상속받아 사용해야하는지 혼동
2) 오버라이딩 (overriding)
class Unit // 부모 클래스
{
String name;
int hp;
void printUnit()
{
System.out.println("이름 : " + name);
System.out.println("HP : " + hp);
}
}
class Marine extends Unit // 자식 클래스
{
int attack;
void printUnit() // 오버라이딩
{
System.out.println("this 이름 : " + name);
System.out.println("this HP : " + hp);
}
void printMarine()
{
printUnit(); // 상속 받은 기능
System.out.println("공격력 : " + attack);
}
}
public class MyTerran
{
public static void main(String[] args)
{
Marine unit1 = new Marine(); // 객체 생성
unit1.name = "마린";
unit1.hp = 100;
unit1.attack = 20;
unit1.printMarine();
}
}
3) 상속이 제한되는 final
4) 추상 클래스
abstract class Unit // 부모 클래스
{
String name; // 멤버 변수
int hp;
abstract void doMove(); // 추상 메서드
void printUnit() // 구상 메서드
{
System.out.println("이름 : " + name);
System.out.println("HP : " + hp);
}
}
class Marine extends Unit // 자식 클래스
{
void doMove() // 구체적인 기능 구현(오버라이딩)
{
System.out.println("마린은 두 발로 이동");
}
}
public class MyStarcraft
{
public static void main(Sting[] args)
{
Marine unit1 = new Marine(); // 객체 생성
unit1.doMove(); // 객체 메서드 호출
}
}
5) 인터페이스
interface A
{
public static final int a = 2; // 스태틱 상수 정의 (public static final 생략 가능)
public abstract void say(); // 추상 메서드 (public abstract 생략 가능)
public default void desc() // 디폴트 메서드
{
System.out.println("기능이 구현된 메서드");
}
}
interface A extends B, C, D // 인터페이스 다중 상속
{
...
}
class X implements B, C, D // 다중 인터페이스 구현
{
...
}
class X extends Y implements B // 상속과 인터페이스
{
...
}
interface X
{
void method1();
default void method2() {};; // 디폴트 메서드
}
class B implements X
{
void method1() {};
void method2() {}; // 오버라이딩
}
6) 다형성 (polymorphism)
abstract class Calc
{
int a = 5;
int b = 6;
abstract void plus();
}
class MyCalc extends Calc
{
void plus() { System.out.println(a + b);
void minus() { System.out.println(a - b);
}
pulbic class Ex01
{
public static void main(String[] args)
{
MyCalc mc1 = new MyCalc();
mc1.plus();
mc1.minus();
Calc mc2 = new MyCalc(); //하위 클래스 객체를 상위 클래스 객체에 대입
mc2.plus();
// mc2.minus(); // 오류 발생
}
}
7) instanceof 연산자
interface Cry
{
void cry();
}
class Cat implements Cry
{
public void cry()
{
System.out.println("야옹");
}
}
class Dog implements Cry
{
public void cry()
{
System.out.println("멍멍");
}
}
public class Ex03{
public static void main(String[] args)
{
Cry test1 = new Cat();
if (test1 instanceof Cat) // test1에 있는 참조값이 어떤 객체 가르키는지 조사 (참)
test1.cry();
else if (test1 instanceof Dog)
System.out.println("고양이가 아닙니다");
}
}
1) String 선언 방법
2) 문자열형 변수의 참조 비교
pulbic class Ex02{
public static void main(String[] args)
{
String str1 = new String("java"); // str1 != str2
String str2 = new String("java");
String str3 = "java"; // str3 = str4
String str4 = "java";
}
}
3) String 클래스의 메서드
eqauls()
: 변수의 내용이 같은지 비교compareTo()
: 변수의 내용이 크다/같다/작다 사전순 비교concat()
: 문자열 합치기 indexOf()
: 문자열에서 문자의 위치 반환 substring()
: 문자열에서 특정 위치의 문자열 잘라냄length()
: 문자열 길이 contains()
: 문자열이 포함되어있는지 조사startsWith()
: 시작하는 문자열이 s인지 조사endsWith()
: 끝나는 문자열이 s인지 조사isEmpty()
: 문자열의 길이가 0이면 true 변환toLowerCase()
: 소문자 변환toUpperCase()
: 대문자 변환trim()
: 앞뒤 공백 제거한 후 변환String.valueOf()
: 기본 자료형의 값을 문자열로 변환1) 배열 선언
2) 기본 자료형
3) String 형
4) 클래스형
5) 매개변수, 반환형
6) for ~ each문
int[] arr = {1, 2, 3, 4, 5};
for (int e : arr)
sum += e;
7) 배열 관련 유틸리티 메서드
fill()
: 배열의 초기화copyOf()
equals()
: 두 배열의 데이터 비교 (배열 길이 다르면 false)sort()
: 배열 내용 오름차순 정렬1) 예외와 에러
2) 예외 종류
3) 예외 처리하기
import java.util.Scanner;
import java.util.InputMismatchException;
public class Ex03 {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
try
{
int num1 = sc.nextInt(); // 에러 발생 시점
int num2 = 10 / num1; // 에러 발생 시점
System.out.println(num2);
}
catch (InputMismatchException e)
{
System.out.println(e.getMessage());
// e.printStactTrace();
}
catch (ArithmeticException e)
{
String str = e.getMessage();
System.out.println(str);
if (str.equals("/ by zero"))
System.out.println("0으로 나눌 수 없습니다");
}
finally // 반드시 실행
{
System.out.println("Good Bye");
}
}
}
4) 예외 처리 미루기(던지기)
import java.util.Scanner;
public class Ex07 {
public static void myMethod1()
{
myMethod2();
}
public static void myMethod2()
{
Scanner sc = new Scanner(System.in);
int num1 = sc.nextInt(); // 에러 발생 시점
int num2 = 10 / num1; // 에러 발생 시점
System.out.println(num2);
}
public static void main(String[] args) {
try
{
myMethod1(); // 여기로 myMethod1으로부터 예외가 넘어옴
}
catch (Trowable e)
{
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
5) 메서드에 예외 선언
public static void myMethod2() throws ArimeticException, InputMismatchException
{
Scanner sc = new Scanner(System.in);
int num1 = sc.nextInt(); // 에러 발생 시점
int num2 = 10 / num1; // 에러 발생 시점
System.out.println(num2);
}
1) java.lang 클래스
2) Object 클래스
toString()
: 객체의 문자 정보 반환equals(Object obj)
: 두 객체가 동일한지 여부 반환 (객체의 주소값 비교, 보통은 오버라이딩하여 객체 안 변수값 비교로 사용)hashcode()
: 객체의 해시 코드 반환clone()
: 객체의 사본 생성3) 래퍼 클래스
기본 자료형(정수형, 문자형, 논리형)에 대해서 객체로 인식되도록 포장한 클래스
기본 자료형 대신 래퍼 클래스 사용 이유
래퍼 클래스 메서드
boolean
byte
char
short
int
long
float
double
valueOf()
max()
min()
sum()
toBinaryString()
toOctalString()
toHexString()
Nuber 클래스
byteValue()
shortValue()
intValue()
longValue()
floatValue()
doubleValue()
//Integer num = new Integer(20);
Integer num = integer.valueOf(20);
System.out.println(num.intValue());
System.out.println(num.doubleValue()); // 형변환하여 반환
문자열 ➡️ 수치형 형변환
parsePyte()
parseShort()
parseInt()
parseLong()
parseFloat()
parseDouble()
오브젝트의 비교
박싱 / 언박싱
// 박싱
Integer iObj = Integer.valueOf(10);
Double dObj = Double.valueOf(3.14);
// 오토박싱
Integer iObj2 = 10;
Double dObj2 = 3.14;
// 메서드 호출을 통한 언박싱
int num1 = iObj.intValue();
double num2 = dObj.doubleValue();
// 오토 언박싱
int num1 = iObj2;
double num2 = dObj2;
// 래퍼 인스턴스 값 증가 방법
iObj = Integer.valueOf(iObj.intValue() + 10);
dObj = Double.valueOf(dObj.doubleValue() + 1.2);
4) Math 클래스
sqrt()
: 제곱근log()
: 로그pow()
: 지수PI()
: 원주율toRadians()
: 라디안으로 변환sin()
: 사인cos()
: 코사인tan()
: 탄젠트5) Random 클래스
nextBoolean()
nextInt()
nextLong()
nextInt()
nextFloat()
nextDouble()
6) Arrays 클래스
Arrays.eqauls()
: 객체 저장 배열의 비교 (기본형 주소값 비교, 오버라이딩하여 사용)Arrays.sort()
: 객체 저장 배열의 정렬1) 열거형
/* interface의 경우 (public static final 변수)
interface Human1 {
int MAN = 1; // 같은 값 가지고 있음
int WOMAN = 2; // 잘못 사용하면 의미 전달에 있어 모호함
}
interface Machine1 {
int TANK = 1;
int AIRPLANE = 2;
}
*/
enum Human2 {MAN, WOMAN}
enum Machine2 {TANK, AIRPLANE}
public class Ex02 {
public calss static void main(String[] args) {
createUnit(Machine2.TANK); // 알맞은 상수 사용
createUnit(Human2.MAN); // 에러 (값이 동일한 잘못된 상수 사용)
if (Hunam2.MAN == 0) // 에러 (숫자로 비교하면 에러가 남)
}
}
2) 가변 인수
public static void Hello(String ... vargs) // 가변 인수 표시
{
for (String s : vargs) // 가변 인수 사용
System.out.println(s);
}
3) 어노테이션
자바 소스 코드에 추가하여 사용할 수 있는 메타 데이터
@Override
interface Unit4
{
public void move(String str);
}
class Human4 implements Unit4
{
@Override
public void move(String str) // 오버라이딩
{
System.out.println(str);
}
}
@Deprecated
interface Unit5
{
@Deprecated
public void move(String str); // move가 run으로 대체됨
public void run(String str);
}
@SuppressWarings
interface Unit5
{
@Deprecated
public void move(String str); // move가 run으로 대체됨
public void run(String str);
}
class Human5 implements Unit5
{
@Override
@SuppressWarings("deprecation")
public void move(String str)
{
System.out.println(str);
}
@Override
public void run (String str)
{
System.out.println(str);
}
}
1) 제네릭의 필요성
class NPC
{
public String toString() {
return "This is a NPC"; // 기대 출력 결과
}
}
class Camp
{
private Object unit;
public void set(Object unit) {
this.unit = unit;
}
public Object get() {
return unit;
}
}
public class Ex03 {
public static void main(String[] args) {
// 객체 생성
Camp human = new Camp();
// (1) 자식 객체를 부모 타입의변수에 대입
human.set(new NPC());
// (2) 만약, Object가 아닌 잘못된 String 대입한다면
human.set("난 공룡");
// 꺼낼 때 형변환 필요
NPC unit = (NPC)human.get();
// (1)의 결과 : This is a NPC
// (2)의 결과 : 난 공룡 (+ 에러 발생)
System.out.println(unit);
}
}
2) 제네릭 기반의 클래스 정의
// 제네릭 사용 결과
class NPC
{
public String toString() {
return "This is a NPC";
}
}
class Camp<T> {
private T unit;
public void set(T Unit) {
this.unit = unit;
}
public T get() {
return unit;
}
}
public class Ex05 {
public static void main(String[] args) {
Camp<NPC> human = new Camp<>();
human.set(new NPC());
NPC unit = human.get();
System.out.println(unit);
}
}
3) 매개변수 여러 개일 때 제네릭 클래스 정의
class Camp<T1, T2>
{
private T1 param1;
private T2 param2;
public void set(T1 o1, T2, o2)
{
param1 = o1;
param2 = 2;
}
public String toString()
{
return param1 + '&' + param2;
}
}
public class Ex07{
public static void main(String[] args)
{
Camp<String, Integer> camp = new Camp<>();
camp.set("Apple", 25);
System.out.println(camp);
}
}
4) 제네릭 클래스의 매개변수 타입 제한
// 매개변수 타입을 제한하지 않은 경우
class Camp<T> {
private T ob;
...
public int toIntValue() {
return ob.intValue(); // 에러 (아무 자료형이나 들어올 수 있음)
}
}
// 매개변수 타입을 제한하는 경우
class Camp<T extends Number> { // Number로 제한
private T ob;
...
public int toIntValue() {
return ob.intValue(); // 정상
}
}
5) 제네릭 메서드의 정의
class MyData
{
public static <T> T showData(T data) // 앞의 <T>가 뒤의 매개변수 자료형을 결정함
{
if (data instanceof String)
System.out.println("String");
else if (data instanceof Integer)
System.out.println("Integer");
else if (data instanceof Double)
System.out.println("Double");
}
}
public class Ex09 {
public static void main(String[] args) {
MyData.<String>showData("Hello"); // 메서드 호출 시점에 데이터 타입 결정
MyData.showData(1); // 타입 인수 생략
MyData.showData(1.0);
}
}
데이터 저장 순서 유지
동일 데이터의 중복 저장 허용
ArrayList<E> : 배열 기반 자료구조 (배열 이용)
import java.util.ArrayList;
import jaava.util.List;
public class Ex01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// 객체 저장 (순서 있음, 중복 허용)
list.add("orange");
list.add("apple");
list.add("apple");
list.add("banana"); // orange, apple, apple, banana
// 객체 참조
for (int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + '\t');
// 첫 번째 객체 삭제
list.remove(0); // apple, apple, banana
}
}
LinkedList<E> : 연결 기반 자료구조 (리스트 이용)
import java.util.LinkedList;
import jaava.util.List;
public class Ex01 {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
// 객체 저장 (순서 있음, 중복 허용)
list.add("orange");
list.add("apple");
list.add("apple");
list.add("banana"); // orange, apple, apple, banana
// 객체 참조
for (int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + '\t');
// 첫 번째 객체 삭제
list.remove(0); // apple, apple, banana
}
}
Iterator 반복자
iterator()
메서드로 반복자 구하기import java.util.Iterator;
import java.util.LinkedList;
import jaava.util.List;
public class Ex01 {
public static void main(String[] args) {
Iterator<String> itr = list.iterator(); // 반복자 획득
String str;
while (itr.hasNext()) // 반복자를 이용한 순차적 참조
{
str = itr.next();
System.out.print(str + '\t');
if (str.equals("orange:)
itr.remove();
}
itr = list.iterator(); // 반복자 다시 획득
while(itr.hasNext()) // 삭제 후 결과 확인
System.out.print(itr.next() + '\t');
}
}
리스트 형식 바꾸기
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import jaava.util.List;
public class Ex01 {
public static void main(String[] args) {
List<String> list = Arrays.asList("홍길동", "전우치", "손오공", "전우치");
// list.add("멀린"); // 에러 (추가 불가)
list = new ArrayList<>(list); // 수정 가능한 객체로 변환
list.add("해리포터");
/* ArrayList<E> 객체의 순환 */
for(Iterator<String> itr = list.iterator(); itr.hasNext(); )
System.out.println();
HashSet<String> set = new HashSet<>(list); // 중복 제거 (ArrayList<E>를 HashSet으로 변환)
list = new LinkedList<>(set); // HashSet를 LinkedList로 변환
/* LinkedList<E> 객체의 순환 */
for (String s : list)
System.out.print(s + '\t');
}
}
컬렉션 프레임워크에 기본 자료형을 데이터로 사용
저장 순서가 유지X
데이터 중복 저장 허용X
HashSet<E>
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Ex01 {
public static void main(String[] args) {
Set<String> set = new HashSet(); // HashSet으로 객체 생성, Set으로 사용
// 객체 저장 (순서 없음, 중복 허용X)
list.add("orange");
list.add("apple");
list.add("apple");
list.add("banana"); // orange, apple, banana
System.out.println(set.size()); // 객체 수
// 반복자를 이용한 전체 출력
for(Iterator<String> itr = set.iterator(); itr.hasNext(); )
System.out.print(itr.next() + '\t');
// 향상된 기능의 for문을 이용한 전체 출력
for (String s : set)
System.out.print(s + '\t'); // orange, apple, banana
}
}
TreeSet<E>
import java.util.Iterator;
import java.util.TreeSet;
public class Ex01 {
public static void main(String[] args) {
TreeSet<String> tree = new TreeSet<>();
// 객체 저장 (순서 없음, 중복 허용X)
tree.add("orange");
tree.add("apple");
tree.add("apple");
tree.add("banana"); // orange, apple, banana
System.out.println(tree.size()); // 객체 수
// 반복자를 이용한 전체 출력
for(Iterator<String> itr = tree.iterator(); itr.hasNext(); )
System.out.print(itr.next() + '\t');
}
}
Queue 구현
import java.util.LinkedList;
import java.util.Queue;
public class Ex01 {
public static void main(String[] args) {
Queue<String> q = new LinkedList<>();
// 데이터 저장
q.offer("A");
q.offer("B");
q.offer("C"); // A B C
System.out.println(que.size()); // 큐 크기
System.out.println(que.peek()); // 다음에 나올 값 확인 (A)
System.out.println(que.poll()); // 객체 꺼내기 (A)
}
}
Stack 구현
import java.util.ArrayDeque;
import java.util.Deque;
public class Ex01 {
public static void main(String[] args) {
Deque<String\> deq = new ArrayDeque<>();
// Deque<String\> deq = new LinkedList<>(); // 동일
// 데이터 (앞) 저장
deq.offerFirst("A");
deq.offerFirst("B");
deq.offerFirst("C"); // C B A
// 데이터 (뒤) 저장)
deq.offerLast("D");
deq.offerLast("E");
deq.offerLast("F"); // C B A D E F
// 데이터 (앞) 꺼내기
System.out.println(deq.pollFirst()); // C
// 데이터 (뒤) 꺼내기
System.out.println(deq.pollLast()); // F
}
}
객체 Key값은 유일, value값 중복 가능
HashMap<K,V>
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class Ex01 {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
// 데이터 저장 (Key-Value 기반)
map.put("홍길동", "010-1234-1443");
map.put("전우치", "010-4321-1446");
map.put("손오공", "010-9876-1443");
// 데이터 확인
System.out.println(map.get("홍길동");
// 데이터 삭제
map.remove("손오공");
/* Key만 담고 있는 컬렉션 객체 생성 */
Set<String> ks = map.keySet();
// 전체 key 출력 (향상된 기능의 for문 기반)
for(String s : ks)
System.out.print(s + '\t');
// 전체 Value 출력 (향상된 기능의 for문 기반)
for(String s : ks)
System.out.print(map.get(s).toString() + '\t');
// 전체 Value 출력 (반복자 기반)
for(Iterator<String> itr = ks.iterator(); itr.hasNext(); )
System.out.print(map.get(itr.next()).toString() + '\t');
}
}
```
TreeMap<K,V>
import java.util.TreeMap;
import java.util.Iterator;
import java.util.Set;
public class Ex01 {
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<>();
// 데이터 저장 (Key-Value 기반)
map.put("홍길동", "010-1234-1443");
map.put("전우치", "010-4321-1446");
map.put("손오공", "010-9876-1443");
/* Key만 담고 있는 컬렉션 객체 생성 */
Set<String> ks = map.keySet();
// 전체 key 출력 (향상된 기능의 for문 기반)
for(String s : ks)
System.out.print(s + '\t');
// 전체 Value 출력 (향상된 기능의 for문 기반)
for(String s : ks)
System.out.print(map.get(s).toString() + '\t');
// 전체 Value 출력 (반복자 기반)
for(Iterator<String> itr = ks.iterator(); itr.hasNext(); )
System.out.print(map.get(itr.next()).toString() + '\t');
}
}
7) 컬렉션 기반 알고리즘
정렬
Collections.sort()
메서드 사용import.java.util.ArrayList;
import.java.util.Arrays;
import.java.util.Collections;
import.java.util.List;
public class Ex01 {
public static void main(String[] args) {
List<String> list = Arrays.asList("홍길동", "전우치", "손오공", "멀린"); // 크기 변경 불가능한 리스트
list = new ArrayList<>(); // 크기 변경 가능하도록 리스트 새로 생성
Collections.sort(list); // 리스트 정렬 (원본 데이터 변경)
}
}
검색
import.java.util.ArrayList;
import.java.util.Collections;
import.java.util.List;
public class Ex01 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("홍길동");
list.add("전우치");
list.add("손오공");
Collections.sort(list); // 정렬
int idx = Collections.binarySearch(list, "홍길동"); // idx = 2
}
}
복사
import.java.util.ArrayList;
import.java.util.Arrays;
import.java.util.Collections;
import.java.util.List;
public class Ex01 {
public static void main(String[] args) {
List<String> src = Array.asList<"홍길동", "전우치", "손오공", "멀린");
// 수정 가능한 리스트 생성
List<String> dst = new ArrayList<>(src);
// 정렬하여 결과 출력
Collections.sort(dst); // 멀린, 손오공, 전우치, 홍길동
// 정렬 이전의 상태로 되돌리기
// 원본 src의 데이터를 dst에 복사
Collections.copy(dst, src); // 홍길동, 전우치, 손오공, 멀린
// 데이터 수정
dst.remove(0); // 전우칭, 손오공, 멀린
}
}
1) 내부 클래스
class MyClass // 외부 클래스
{
static clas NestedClass{} // 스태틱 중첩 클래스
class c1{} // 멤버 내부 클래스
public void myFunc()
{
class c2{} // 지역 내부 클래스
}
}
2) 멤버 내부 클래스
class Outer // 외부 클래스
{
private int speed = 10;
class MemberInner // 멤버 내부 클래스
{
public void move()
{
// 외부 클래스의 자원(speed 변수) 사용 가능
System.out.prinf(speed);
}
}
public void getMarine() // 외부 클래스의 메서드에서 내부 클래스 객체 만들고 참조 가능
{
MemberIneer ineer = new MemberIneer();
inner.move();
}
}
public class Ex01 {
public static void main(String[] args)
{
Outer out = new Outer();
out.getMarine(); // out 기반으로 생성된 객체의 메서드 호출
Outer.MemberInner in = out.new MemberInner(); // out 기반으로 내부 클래스 객체 생성
inner.move(); // inner 기반으로 생성된 객체의 메서드 호출
}
}
3) 지역 내부 클래스
class HumanCamp
{
private int speed = 10;
public void getMarine()
{
class Marine // 지역 내부 클래스
{
public void move() {
System.out.println(speed); // 내부 클래스라서 외부 클래스 자원 사용 가능
}
}
Marine inner = New Marine(); // 해당 메서드 안에서만 생성 가능 (객체의 생성 제한)
inner.move();
}
}
public calss Ex02 {
public static void main(String[] args) {
HumanCamp hc = new HumanCamp();
hc.getMarine();
}
}
4) 익명 내부 클래스
interface Unit
{
void move();
}
class HumanCamp
{
private int speed = 10;
// class Marine implements Unit
// {
// public void move()
// {
// System.out.println(speed);
// }
// }
// return new Marine();
// 이름 생략, 이름이 없으므로 부모 클래스나 인터페이스 이름 사용
return new Unit()
{
public void move()
{
System.out.println(speed);
}
}
}
public class Ex04 {
public static void main(String[] args) {
HumanCamp hc = new HumanCamp();
Unit unit = hc.getMarine();
unit.move();
}
}
5) 람다식
자바에서 클래스 만들고, 클래스 안에 기능을 구현한 만든 후 객체로 메서드 호출하는 불편함 해소
인터페이스의 메서드는 무조건 구현이 필요해서, 람다식이 인터페이스의 메서드에 할당됨
익명 내부 클래스 ➡️ 람다식
interface Unit
{
void move(String s);
}
public class Ex06 {
public static void main(String[] args) {
Unit unit = new Unit() // 인터페이스 메서드를 익명 클래스로 구현
{
public void move(String s)
{
System.out.println(s);
}
};
unit.move();
}
}
@FuntionalInterface
interface Unit // 인터페이스에 메서드 추가시 에러 발생
{
void move(String s);
}
@FuntionalInterface
interface Unit2
{
void calc(int a, int b);
}
@FuntionalInterface
interface Unit3
{
String move();
}
public class Ex06 {
public static void main(String[] args) {
Unit unit;
/* 매개변수 1개 */
unit = (String s) -> { System.out.println(s); };
// 중괄호 구현부가 1문장이면 중괄호 생략 가능
unit = (String s) -> System.out.println(s);
// 매개변수 1개이면 자료형 생략 가능
unit = (s) -> { System.out.println(s); };
// 매개변수 1개이면 소괄호 생략 가능
unit = s -> System.out.println(s);
// (오류) 구현부에 return 있을 경우 중괄호 생략X
unit = (String s) -> return s.length();
/* 매개변수 2개 */
Unit2 unit2;
unit2 = (a, b) -> { return a + b; };
// (오류) 매개변수 2개 이상이면 소괄호 생략X
unit2 = a, b -> { return a + b; };
// (오류) 매개변수 2개 이상이면 중괄호 생략X
unit2 = (a, b) -> return a + b;
// 구현부에 return만 있을 경우 return과 중괄호 생략 가능
unit = s -> s.length();
unit2 = (a, b) -> a + b;
/* 매개변수 0개 */
Unit3 unit3;
// 매개변수 없을 경우 소괄호 생략X
unit3 = () -> { return "Hi"; };
System.out.println(unit3.move());
}
}
6) 함수형 인터페이스
1) 스트림
2) 중간 연산, 최종 연산
filter()
: 조건에 맞는 요소 추출map()
: 조건에 맞는 요소 변환sorted()
: 정렬forEach()
: 요소를 하나씩 꺼냄count()
: 요소 개수sum()
: 요소 합import java.util.Arrays;
import java.util.stream.IntStream;
public class Ex01 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4. 5};
// 스트림 생성
IntStream stm1 = Arrays.stream(arr);
// 중간 연산
IntStream stm2 = stm1.filter(n -> n%2 == 1);
// 최종 연산
int sum = stm2.sum();
System.out.println(sum);
}
}
3) 파이프라인 구성
import java.util.Arrays;
public class Ex02 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
// Pipeline 구성
int sum = Arrays.stream(arr) // 스트림 생성
.filter(n -> n%2 == 1) // 중간 연산
.sum(); // 최종 연산
System.out.println(sum);
}
}
4) 컬렉션 객체 vs 스트림
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Ex03 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
// 컬렉션 프레임워크를 이용한 방식
for (int i : arr) { // 필터링
if (i%2 == 1)
{
list.add(i);
}
}
Collections.sort(list); // 정렬
for (int i : list) { // 요소 추출
System.out.print(i + "\t");
}
// Stream 이용한 방식
Arrays.stream(arr)
.filter(n -> n%2 == 1) // 필터링
.sorted() // 정렬
.forEach(n -> Stream.out.print(n + "\t"); // 요소 추출
}
}
5) 여러 가지 중간 연산
sorted()
import java.util.Array;
import java.util.list;
public class Ex04 {
public static void main(String[] args) {
List<String> List = Arrays.asList("홍길동", "멀린", "해리포터");
// 사전순 정렬
list.stream()
.sorted()
.forEach(n -> System.out.print(n + "\t");
// 글자 길이순 정렬
list.stream()
.sorted((s1, s2) -> s1.length() - s2.length())
.forEach(n -> System.out.print(n + "\t");
System.out.println();
}
}
map()
import java.util.Array;
import java.util.list;
public class Ex05 {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "orange");
list.steam()
.map(s -> s.toUpperCase()) // 데이터를 하나씩 받아서 대문자로 변환
.forEach(n -> System.out.print(n + "\t"));
System.out.println();
}
}
sum(), count(), average(), min(), max()
import java.util.stream.IntStream;
public class Ex06 {
public static void main(String[] args) {
// 합
int sum = IntStream.of(1, 3, 5. 7. 9)
.sum();
System.out.println(sum);
// 개수
long cnt = IntStream.of(1, 3, 5. 7. 9)
.count();
System.out.println(cnt);
// 평균
IntStream.of(1, 3, 5. 7. 9)
.average()
.ifPresent(avg -> System.out.println(avg));
// 최소
IntStream.of(1, 3, 5. 7. 9)
.min()
.ifPresent(min -> System.out.println(min));
// 최대
IntStream.of(1, 3, 5. 7. 9)
.max()
.ifPresent(max -> System.out.println(max));
}
}
reduce()
// 문자열 길이를 세서 긴 문자열 남기기
import java.util.Arrays;
import java.util.List;
public class Ex06 {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("홍길동", "전우치", "손오공");
String name1 = list1.stream()
.reduce("이순신", (s1, s2) ->
s1.length() >= s2.length() ? s1 : s2);
System.out.println(name1); // 이순신
List<String> list2 = Arrays.asList("해리포터", "호그와트", "그리핀도르");
String name2 = list2.stream()
.reduce("김수현", (s1, s2) ->
s1.length() >= s2.length() ? s1 : s2);
System.out.println(name2); // 해리포터 (길이가 같을 경우 초기값 남음)
}
}
1) 자바의 입출력 스트림
2) 입출력 스트림의 구분
3) 파일 대상 입출력 스트림 생성
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Ex01 {
public static void main(String[] args) throws IOException {
OutputStream out = new FileOutputStream("data.txt"); // 파일 생성하고, 파일에 스트림 생성
out.write(65); // 스트림을 통해 데이터 전송 (ASCII 코드 65 = 'A')
out.close(); // 파일 닫기
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Ex02 {
public static void main(String[] args) {
OutputStream out = null;
try
{
out = newFileOutputStream("data.txt");
out.write(65);
}
catch (IOException e)
{
}
finally
{
if (out != null)
{
try
{
out.close(); // 에러 발생해도 확실히 종료하기 위해 finally로 이동
}
catch (IOException e2)
{
}
}
}
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Ex02 {
public static void main(String[] args) {
try (OutputStream out = new FileOutputStream("data.txt")) // 스트림 닫지 않아도 자바에서 자동 처리
{
out.write(65);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Ex02 {
public static void main(String[] args) {
try (InputStream in = new FileInputStream("data.txt"))
{
int dat = in.read(); // 데이터 1바이트 읽음
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
public class Ex02 {
public static void main(String[] args) {
String src = "./src/FileRead.java";
String dst = "FileRead1.txt";
try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst))
{
Instant start = Instant.now(); // 복사에 걸린 시간 측정을 위해 시간 클래스 이용해 현재 시각 구함
int data;
while(true) // 한 바이트씩 소스 파일의 스트림으로부터 데이터 읽어 대상 파일 스트림에 써줌
{
data = in.read();
if(data == -1) // 더 이상 데이터 읽지 못하면 -1 반환
break;
out.write(data);
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis()); // 복사에 걸린 시간
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
public class Ex02 {
public static void main(String[] args) {
String src = "./src/FileRead.java";
String dst = "FileRead1.txt";
try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst))
{
byte[] buf = new byte[1024]; // 데이터 담을 버퍼로 바이트 배열 1KB 크기 생성
int len;
Instant start = Instant.now();
int data;
while(true) // 버퍼 크기만큼 한 번에 읽음
{
len = in.read(buf);
if(len == -1)
break;
out.write(buf, 0, len);
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis()); // 복사에 걸린 시간
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
4) 보조 스트림
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
public class Ex02 {
public static void main(String[] args) {
String src = "./src/FileRead.java";
String dst = "FileRead1.txt";
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst))) // 기반 스트림에 없는 기능 추가 (기반 스트림 : FileInputStream, 보조 스트림 : BufferedInputStream)
{
Instant start = Instant.now();
int data;
while(true) // 1 바이트씩 읽고 있지만 보조 스트림에 의해 버퍼링처럼 동작
{
data = in.read();
if(data == -1)
break;
out.write(data);
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis()); // 복사에 걸린 시간
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
5) 문자 스트림
import java.io.FileWriter;
import java.io.Writer;
import java.io.IOException;
public class Ex01 {
public static void main(String[] args) {
try(Writer out = new FileWriter("text.txt"))
{
for(int ch = (int)'A'; ch < (int)('Z' + 1); ch++)
out.write(ch); // char를 int로 형변환해서 A부터 Z까지 반복
// out.write("\r\n")과 동일
out.write(13); // 캐리지 리턴 값 저장 (현재 위치 커서를 맨 앞으로 이동)
out.write(10); // 라인 피드 값 저장 (커서 위치를 아랫줄로 이동)
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
import java.io.FileReader;
import java.io.Reader;
import java.io.IOException;
public class Ex01 {
public static void main(String[] args) {
try (Reader in = new FileReader("text.txt"))
{
int ch;
while(true)
{
ch = in.read(); // 문자를 스트림으로부터 하나 읽어 int형 변수에 대입
if (ch == -1) // 더 이상 읽을 수 없을 때 -1 반환받기 위해 int 사용
break;
System.out.println((char)ch);
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
import java.io.BufferedWriter;
import java.io.FileWriter
import java.io.IOException;
public class Ex01 {
public static void main(String[] args) {
String str1 = "동해물과";
String str2 = "백두산이";
try (BufferedWriter bw = new BufferedWriter(new FileWriter("text.txt"))) // 기반 스트림 : FileWriter, 보조 스트림 : BufferedWriter
{
bw.write(str1, 0, str1.length()); // 문자열의 크기만큼 버퍼링하여 한 번에 출력 스트림으로 저장
bw.newLine(); // 줄바꿈 문자를 스트림으로 저장
bw.write(str2, 0, str2.length());
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Ex01 {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("text.txt")))
{
String str;
while(true)
{
str = br.readLine(); // 입력 스트림에서 라인별로 구분하여 데이터를 읽어들임
if (str == null)
break;
System.out.println(str);
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
6) IO 스트림 기반의 인스턴스 저장
직렬화
public class Ex12 implements java.io.Serializable
{
private static final long serialVersionUID = 1L; // 직렬화에 사용되는 고유 아이디 (없으면 JVM에서 디폴트로 자동 생성)
private String name;
public Ex12 (String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
ObjectOutputStream
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
public class Ex13 {
public static void main(String[] args) {
Ex13 unit1 = new Ex13("Marine");
Ex13 unit2 = new Ex13("Medic");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Object.bin")))
{
oos.writeObject(unit1);
oos.writeObject(unit2);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
ObjectInputStream
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
public class Ex13 {
public static void main(String[] args) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Object.bin")))
{
Ex13 unit1 = (Ex13) ois.readObject();
System.out.println(unit1.getName());
Ex13 unit2 = (Ex13) ois.readObject();
System.out.println(unit2.getName());
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
1) 스레드의 이해
2) 스레드 생성과 실행
Thread 클래스를 상속받아 만들기
class MyThread extends Thread
{
public void run()
{
int sum = 0;
for (int i = 0; i < 10; i++)
sum += i;
String name = Thread.currentThread().getName(); // 현재 스레드명 name = Thread-0
}
}
public class Ex02 {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
System.out.println(Thread.currentThread().getName()); // main 출력
}
}
Runnable 인터페이스 구현
class MyThread implements Runnable
{
public void run()
{
int sum = 0;
for (int i = 0; i < 10; i++)
sum += i;
String name = Thread.currentThread().getName(); // 현재 스레드명 name = Thread-0
}
}
public class Ex02 {
public static void main(String[] args) {
Thread t = new Thread(new MyThread());
t.start();
System.out.println(Thread.currentThread().getName()); // main 출력
}
}
람다식으로 Runnable 구현
public class Ex02 {
public static void main(String[] args) {
Runnable task = () -> {
try
{
Thread.sleep(3000);
}
catch(Exception e) {}
int sum = 0;
for (int i = 0; i < 10; i++)
sum += i;
String name = Thread.currentThread().getName(); // 현재 스레드명 name = Thread-0
};
Thread t = new Thread(task);
t.start();
System.out.println(Thread.currentThread().getName()); // main 출력
}
}
public class Ex02 {
public static void main(String[] args) {
Runnable task1 = () -> {
try
{
for (int i = 0; i < 20; i = i + 2)
{
System.out.print(i + " ");
Thread.sleep(1000); // 1000밀리세컨드(1초) 쉼
}
}
catch(InterruptedException e) {}
};
Runnable task2 = () -> {
try
{
for (int i = 9; i > 0; i--)
{
System.out.print("(" + i + ")");
Thread.sleep(500); // 500밀리세컨드 쉼
}
}
catch(InterruptedException e) {}
};
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
}
}
3) 스레드 동기화
public class Ex02 {
public static int money = 0;
public static void main(String[] args) throws InterruptedException {
Runnable task1 = () -> {
for (int i = 0; i < 10000; i++)
money++;
};
Runnable task2 = () -> {
for (int i = 0; i < 10000; i++)
money--;
};
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
t1.join(); // t1이 참조하는 스레드의 종료를 기다림
t2.join(); // t2이 참조하는 스레드의 종료를 기다림
System.out.println(money); // 스레드가 종료되면 출력을 진행함
}
}
- 스레드 동기화로 해결
- 메서드에 synchronized 키워드 지정
```java
public synchronized static void 메서드()
{
// 동기화 대상 코드
}
public void 메서드()
{
synchronized(공유 객체)
{
// 동기화 대상 코드
}
}
4) 스레드 풀
import java.util.concurrent.ExcutorService;
import java.util.concurrent.Executors;
public class Ex08 {
public static int money = 0;
public static void main(String[] args) {
Runnable task1 = () -> {
for (int i = 0; i < 10000; i++)
money++;
String name = Thread.currentThread().getName(); // pool-1-thread-1
};
Runnable task2 = () -> {
for (int i = 0; i < 10000; i++)
money--;
String name = Thread.currentThread().getName(); // pool-1-thread-1
};
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.submit(task1); // 스레드 풀에 작업을 전달
pool.submit(task2);
System.out.println(Thread.currentThread().getName()); // main
pool.shutdown(); // 스레드 풀과 그 안에 있는 스레드 소멸
}
}
import java.util.concurrent.ExcutorService;
import java.util.concurrent.Executors;
public class Ex08 {
public static void main(String[] args) {
Runnable task1 = () -> {
String name = Thread.currentThread().getName(); // pool-1-thread-1
try
{
Thread.sleep(5000);
}
catch (Exception e) { }
};
Runnable task2 = () -> {
String name = Thread.currentThread().getName(); // pool-1-thread-2
};
Runnable task3 = () -> {
String name = Thread.currentThread().getName(); // pool-1-thread-2
try
{
Thread.sleep(2000);
}
catch (Exception e) { }
};
ExecutorService pool = Executors.newFixedThreadPool();
pool.submit(task1); // 스레드 풀에 작업을 전달
pool.submit(task2);
pool.submit(task3);
pool.shutdown(); // 스레드 풀과 그 안에 있는 스레드 소멸
}
}
5) Callable & Future
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Ex10 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<Integer> task1 = () -> { // Callable과 사용할 자료형을 제네릭으로 지정하여 스레드 생성
Thread.sleep(2000);
return 2 + 3; // 제네릭에서 지정한 형태의 값을 반환
};
Callable<Integer> task2 = () -> {
Thread.sleep(10);
return 2 * 3;
};
ExecutorService pool = Executors.newFixedThreadPool(2); // 스레드 풀 생성 (동시에 두 스레드 처리 가능)
Future<Integer> future1 = pool.submit(tast1); // 스레드를 스레드 풀에 전달함 (스레드 풀은 전달된 스레드를 실행시킴)
Future<Integer> future2 = pool.submit(tast2);
Integer r1 = future1.get(); // Future형의 변수에서 get() 메서드를 통해 스레드에서 반환 값 구해옴
Integer r2 = future2.get();
pool.shutdown(); // 마지막 스레드가 종료되면 스레드 풀 종료
}
}
6) ReentrantLock 클래스 : 명시적 동기화
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
class BankAccount
{
ReentrantLock myLock = new ReentrantLock();
int money = 0;
public void deposit()
{
myLock.lock(); // 동기화 시작점 설정
money++;
myLock.unlock(); // 동기화 끝점 설정
}
public void withdraw()
{
myLock.lock();
money--;
myLock.unlock();
}
public int balance()
{
return money;
}
}
public class Ex11 {
public static BankAccount account = new BankAccount();
public static void main(String[] args) throws InterruptedException {
Runnable task1 = () -> {
for (int i = 0; i < 10000; i++)
accout.deposit();
}
Runnable task2 = () -> {
for (int i = 0; i < 10000; i++)
accout.withdraw();
}
ExecutorService pool = Executors.newFixedThreadPool(2); // 스레드 풀 생성 (스레드 동시에 2개까지 처리 가능)
pool.submit(task1);
pool.submit(task2);
pool.shutdown(); // 스레드 종료되면 스레드 풀 종료
pool.awaitTermination(100, TimeUnit.SECONDS); // 스레드 풀이 완전하게 종료되도록 대기
System.out.println(accout.balance()); // 0
}
}
7) 컬렉션 객체 동기화
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Ex13 {
public static List<Integer> list = new ArrayList<>();
public static void main(String[] args) throws InterruptedException
{
for (int i = 0; i < 10; i++)
list.add(i);
Runnable task = () -> { // list 객체 사용할 때 객체에 동기화 Lock 설정
synchronized(list)
{
ListIterator<Integer> itr = list.listIterator();
while (itr.hasNext())
itr.set(itr.next() + 1);
}
};
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.shutdown();
pool.awaitTermination(100, TimeUnit.SECONDS);
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Ex13 {
// public static List<Integer> list = new ArrayList<>();
public static List<Integer> list = Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) throws InterruptedException
{
for (int i = 0; i < 10; i++)
list.add(i);
Runnable task = () -> {
synchronized(list)
{
ListIterator<Integer> itr = list.listIterator();
while (itr.hasNext())
itr.set(itr.next() + 1);
}
};
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.shutdown();
pool.awaitTermination(100, TimeUnit.SECONDS);
}
}
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Ex13 {
public static Map<String, Integer> syncMap = null; // 컬렉션 객체를 담을 변수를 선언
public static Map<Stirng, Integer> concMap = null;
public static void performanceTest(final Map<String, Integer> target) throws InterruptedException
{
System.out.println(Thread.currentThread().getName()); //main
Instant start = Instant.now();
Runnable task = () -> { // 스레드 생성
for (int i = 0; i < 10000; i++)
target.put(String.valueOf(i), i);
};
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.submit(task);
pool.shutdown();
pool.awaitTermination(100, TimeUnit.SECONDS);
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
}
public static void main(String[] args) throws InterruptedException
{
syncMap = Collections.synchronizedMap(new HashMap<>());
performanceTest(syncMap);
concMap = new ConcurrentHashMap<>(); // 속도 더 빠름
performanceTest(concMap);
}
}