자바14일차

달달한스위츠·2024년 2월 20일

자바배우기

목록 보기
14/43

오늘의 코드

package edu.java.inner01;

// 변수 선언 :
// 1. 멤버 변수(필드) : 클래스에서 선언된 변수
//  - 클래스 내부 어느 곳에서나 사용할 수 있는 변수
//  - 수식어(public, private, static, ...)를 사용할 수 있음
// 2. 지역 변수 : 메소드 안에서 선언하는 변수
//  - 지역 변수가 선언된 곳에서 변수가 속한 블록({})이
// 끝나는 곳까지 사용할 수 있는 변수
//  - 접근 수식어(public, private, static, ...)를 사용할 수 없음
//  - final은 가능

// 내부 클래스(Inner Class) : 다른 클래스 내부에서 정의된 클래스
// 1. 멤버 내부 클래스(member inner class)
//  - 멤버 변수를 선언하는 위치에서 정의하는 내부 클래스
//  - 외부 클래스의 인스턴스가 생성되어야만 객체 생성이 가능함
// 2. static 내부 클래스(static inner class), 중첩 클래스(nested class)
//  - 멤버 변수를 선언하는 위치에서 static으로 정의한 내부 클래스
//  - 외부 클래스의 인스턴스를 생성하지 않아도 객체 생성이 가능함
//  - 외부 클래스와 상관이 없는 클래스라고 생각해도 됨
// 3. 지역 내부 클래스(local inner class) : 메소드 안에서 정의하는 클래스
// 4. 익명 클래스(Anonymous class) : 이름이 없는 내부 클래스
// -> 람다 표현식 사용 가능

public class InnerMain01 {

	public static void main(String[] args) {
		
		// 외부 클래스 OuterClass의 인스턴스를 생성
		OuterClass out1 = new OuterClass(100);
		out1.display();

		// 내부 클래스의 인스턴스 생성:
		// (외부 클래스 이름).(내부 클래스 이름) 변수이름 =
		// (외부 클래스의 참조변수).new (내부 클래스 생성자)();
		OuterClass.InnerClass inner1 = out1.new InnerClass(200); // 사람을 만들고 심장을 이식하는 형태
		inner1.printValues();

		System.out.println();
		// 내부 클래스의 인스턴스를 통한 외부 클래스 멤버 변수 변경
		inner1.setOuterValue(300);
		inner1.printValues();
		out1.display();

	} // end main()

} // end InnerMain01
package edu.java.inner01;

public class OuterClass {
// 멤버 변수
	private int value1;

	// 생성자
	public OuterClass(int v) {
		this.value1 = v;
	}

	// 메소드
	public void display() {
		System.out.println("value1 = " + value1);
	}

	class InnerClass {
		private int value2;

		public InnerClass(int v) {
			this.value2 = v;

		}

		// 외부 클래스의 멤버 변수는 내부 클래스에서 직접 사용이 가능
		public void setOuterValue(int value) {
			value1 = value;
		}

		public void printValues() {
			// 외부 클래스의 멤버 변수 출력
			System.out.println("outer value : " + value1);
			
			// 내부 클래스의 멤버 변수 출력
			System.out.println("inner value : " + value2);
		}

	} // end InnerClass

} // end OuterClass
package edu.java.inner02;

// 멤버 내부 클래스(member inner class)를 사용하는 경우
// 상속관계로는 묶을 수 없지만,
// A라는 객체가 생성된 이후에만 존재할 수 있는 B라는 객체가 있다면
// B를 A의 내부 클래스로 정의
// (예) 자동차 - 타이어, PC- CPU/RAM 등
public class Car {
	private String name;
	
	public Car(String name) {
		this.name = name;
	}
	
	// 멤버 내부 클래스(member inner class)
	public class Tire { 
		private int size;
		
		public Tire(int size) {
			this.size = size;
		}
		
		public void display() {
			System.out.println("--- 자동차 정보 ---");
			System.out.println("자동차 이름 : " + name);
			System.out.println("타이어 크기 : " + size);
		} // end display()
		
	} // end Tire
	

} // end Car
package edu.java.inner02;

public class InnerMain02 {

	public static void main(String[] args) {
		Car car1 = new Car("롤스로이스 보트 테일");
		Car.Tire tire = car1.new Tire(20);
		tire.display();

		System.out.println();
		Car car2 = new Car("제네시스");
		Car.Tire tire2 = car2.new Tire(15);
		tire2.display();

	} // end main()

} // end InnerMain02
package edu.java.inner03;

// 외부 클래스
class OuterTest {
	private int value;
	public OuterTest(int value) {
		this.value = value;
	}
	public void printValue() {
		System.out.println("value = " + value);
	}
	
	// 멤버 내부 클래스
	class InnerTest {
		private int value;
		
		public InnerTest(int value) {
			this.value = value;
		}
		
		// 외부 클래스의 멤버 변수 이름과
		// 내부 클래스의 멤버 변수 이름이 같을때
		// 외부 클래스의 멤버 변수를 참조하는 방법
		public void displayValues() {
			System.out.println("value = " + value);
			System.out.println("this.value = " + this.value);
			System.out.println("OuterTest.this.value = " 
						+ OuterTest.this.value );
		}
		
	} // end InnerTest
	
} // end OuterTest

public class InnerMain03 {

	public static void main(String[] args) {
		OuterTest out = new OuterTest(100);
		out.printValue();
		
		System.out.println();
		OuterTest.InnerTest inner = out.new InnerTest(200);
		inner.displayValues();

	} // end main()

} // end InnerMain03
package edu.java.inner04;

// 외부 클래스
class OuterClass {
	int value;
	static int count = 0;
	public OuterClass(int value) {
		this.value = value;
	}
	
	// static 내부 클래스(중첩 클래스, nested class)
	static class NestedClass {
		private String name;
		
		public NestedClass(String name) {
			this.name = name;
		}
		
		public void display() {
//			System.out.println("value = " + value);
			// 외부 클래스의 static이 아닌 변수는 참조할 수 없음!
			
			System.out.println("count = " + count);
			// 외부 클래스에서 static으로 선언된 변수는 참조 가능
			
			System.out.println("name = " + name);
		} // end display()
		
	} // end NestedClass
	
} // end OuterClass

public class InnerMain04 {

	public static void main(String[] args) {
		// static 멤버 변수 사용 : (클래스이름).(변수이름)
		OuterClass.count = 100;
		System.out.println(OuterClass.count);
		
		// 중첩 클래스(static 클래스)
		// (외부클래스 이름).(중첩클래스 이름) 변수이름 =
		// 		new (외부클래스 이름).(내부클래스 이름)();
		OuterClass.NestedClass nest = 
				new OuterClass.NestedClass("Peter");
		nest.display();


	} // end main()

} // end InnerMain04
package edu.java.inner05;

class OuterClass {
	private int value;
	
	public OuterClass(int value) {
		this.value = value;
	} // end OuterClass
	
	public void test() { // 지역 변수또한 이 안에서 만 사용
		int x = 123; // 지역 변수(local variable)
		
		// 지역 변수를 선언하는 위치에서 정의하는 클래스 : 지역 클래스
		// 여기서 생성하고 여기서 부를려고 만든 것
		class LocalClass {
			private int value2; // 지역클래스의 멤버 변수
			
			// 지역 클래스의 생성자
			public LocalClass(int value2) {
				this.value2 = value2;
			}
			
			// 지역 클래스의 메소드
			public void display() {
				// 외부 클래스의 멤버 변수를 참조 가능
				System.out.println("value = " + value);
				
				// 메소드의 지역 변수 사용 가능
				System.out.println("x = " + x);
				
				// 지역 클래스의 멤버 변수를 참조 가능
				System.out.println("value2 = " + value2);
			} // end display()
			
		} // end LocalClass
		
		// 지역 클래스의 인스턴스 생성 - 메소드 안에서만 가능(필수!!!)
		LocalClass local = new LocalClass(1234);
		// 일회용품 사용하고 버리는 형식이다.
		local.display();
		
	} // end test()
	
} // end OuterClass

public class InnerMain05 {

	public static void main(String[] args) {
		OuterClass outer = new OuterClass(100);
		outer.test();
	} // end main()

} // end InnerMain05
package edu.java.inner06;

interface PersonInterface {
	public abstract void showInfo();
	
	public abstract void hello();
}

class Person {
	private String name; // 멤버 변수
	
	// 생성자
	public Person(String name) {
		this.name = name;
	}
	
	// 메소드
	public PersonInterface setAge(int age) {  // 리턴 타입 : PersonInterface
		// 지역클래스
		class PersonWithAge implements PersonInterface {
			private int age; // 지역 클래스의 멤버 변수
			
			public PersonWithAge(int age) {
				this.age = age;
			}
			@Override
			public void showInfo() {
				System.out.println("이름 : " + name);
				System.out.println("나이 : " + age);
			}

			@Override
			public void hello() {
				System.out.println("안녕하세요!");
			}
			
		} // end PersonWithAge
		
		// 지역 클래스 객체(내용)을 모두 저장
		PersonWithAge instance = new PersonWithAge(age);
		
		// 지역 클래스 객체(내용)을 리턴
		return instance;
		
	} // end setAge()
	
} // end Person

public class InnerMain06 {

	public static void main(String[] args) {
		// 지역 클래스의 메소드들을 외부에서 사용하는 사용하는 방법 :
		// 1. 지역 클래스의 메소드들을 선언한 인터페이스를 정의
		// 2. 지역 클래스가 인터페이스를 구현하도록 정의
		// 3. 다형성 사용하여 메소드의 리턴타입으로 인터페이스를 사용할 수 있음
		
		Person p = new Person("목쌤");
		PersonInterface instance = p.setAge(24);
		instance.showInfo();
		instance.hello();
		
	} // end main()

} // end InnerMain06
package edu.java.inner07;


interface Hello {
	public abstract void hello();
} // end Hello

class Person implements Hello {
	@Override
	public void hello() {
		System.out.println("안녕?");
	}
} // end Person

class Dog implements Hello {
	@Override
	public void hello() {
		System.out.println("멍멍?");
	}
} // end Dog

public class InnerMain07 {

	public static void main(String[] args) {
		Person p1 = new Person(); // 원래 형태1
		p1.hello();
		
		Hello p2 = new Person(); // 원래 형태2 (다형성)
		p2.hello();
		
		Hello dog = new Dog(); // 원래 형태3 
		dog.hello();
		
		// 코드가 길다! (인터페이스는 인스턴스 생성이 불가능)
		// 하지만 상속받아서 사용은 가능하다(뭔이런)
		// - 여기서 바로 implements 처리를 한 것(이것이 익명 클래스)
		Hello cat = new Hello() {
			@Override
			public void hello() {
				System.out.println("야옹?");
			}
		};
		cat.hello();
		
		// new Hello() { 본체 }
		// 본체 : Hello interface를 구현하는 클래스의 내용(객체)
		
		// ******************* 익명 클래스를 사용하는 이유 *****************************
		// - 인터페이스의 메소드가 한 개인 경우,
		//   클래스 외부에서 선언하여 implements하지 않고 사용하기 위해
		// - 익명 클래스를 사용하면 클래스를 외부에서 생성할 필요가 없음
		// - 객체를 한 번 생성하고 더 이상 생성하지 않을 경우 사용
		

	} // end main()

} // end InnerMain07
package edu.java.inner08;

public class Button {
	// 내부 인터페이스
	public interface OnClickListener {
		public abstract void onClick();
	}
	
	private OnClickListener listener;
	
	public void setOnClickListener(OnClickListener listener) {
		this.listener = listener;
	}
	
	public void click() {
		listener.onClick();
	}

}
package edu.java.inner08;

class OkListener implements Button.OnClickListener{

	@Override
	public void onClick() {
		System.out.println("<<< 확인 >>>");
	}
	
} // end OkListener

class CancelListener implements Button.OnClickListener {

	@Override
	public void onClick() {
		System.out.println("<<< 취소 >>>");
	}
	
} // end CancelListener

public class InnerMain08 {

	public static void main(String[] args) {
		Button btnOk = new Button();
		Button.OnClickListener okListener = new OkListener();
		btnOk.setOnClickListener(okListener);
		btnOk.click();
		
		System.out.println();
		Button btnCancel = new Button();
		btnCancel.setOnClickListener(new CancelListener());
		btnCancel.click();
		
		System.out.println();
		Button btn = new Button();
		Button.OnClickListener l = new Button.OnClickListener() {
			@Override
			public void onClick() {
				System.out.println("테스트 클릭");
			}
		};
		btn.setOnClickListener(l);
		btn.click();
		
		btn.setOnClickListener(new Button.OnClickListener() {
			
			@Override
			public void onClick() {
				System.out.println("테스트 클릭2");
			}
		});
		btn.click();

	} // end main()

} // InnerMain08

람다

package edu.java.lambda01;

// FunctionalInterface : 추상 메소드가 하나뿐인 메소드
// 람다(lambda) 표현식은 function interface만 사용 가능

@FunctionalInterface
public interface Adder {
	public abstract double add(double x, double y);
}
package edu.java.lambda01;

class AdderImple implements Adder {

	@Override
	public double add(double x, double y) {
		System.out.println(x + ", " + y);
		return x + y;
	} // end add()
	
} // end AdderImple

public class LambdaMain01 {

	public static void main(String[] args) {
		System.out.println("[1] 인터페이스를 구현하는 클래스 사용");
		AdderImple adder1 = new AdderImple();
		double result = adder1.add(2.0, 4.0);
		System.out.println("result = " + result);

		
		System.out.println("[2] 다형성 사용");
		Adder adder2 = new AdderImple();
		result = adder2.add(1.1, 2.2);
		System.out.println("result = " + result);
		
		
		System.out.println("[3] 익명 클래스 사용");
		Adder adder3 = new Adder() {
			@Override
			public double add(double x, double y) {
				return x + y;
			}
		}; // end Adder()		
		result = adder3.add(2.0, 1.0);
		System.out.println("result = " + result);
		
		
		System.out.println("[4] 람다 클래스 사용");
		Adder adder4 = (x, y) -> x + y;
		result = adder4.add(1.1, 2.2);
		System.out.println("result = " + result);
		
	} // end main()

} // end LambdaMain01
package edu.java.lambda02;

@FunctionalInterface
interface Test1 {
	public abstract void testPrint();
}

@FunctionalInterface
interface Test2 {
	public abstract void testPrint(int n);
}

public class LambdaMain02 {

	public static void main(String[] args) {
		System.out.println("- 익명 클래스, 람다 표현식 연습 -");
		// 람다(Lambda) 표현식
		// (매개변수1, 매개변수2, ..) -> { 실행문; 리턴; }
		// 매개변수와 리턴타입 형태는 인터페이스의 추상메소드에 따라 결정됨
		// 인터페이스 변수이름 = 람다 표현식
		
		// 1. "익명 클래스 연습!"을 출력하는 익명 클래스 생성 및 출력하기
		Test1 test1 = new Test1() {
			
			@Override
			public void testPrint() {
				System.out.println("익명 클래스 연습!");
			}
		};
		test1.testPrint();
		
		// 2. "람다 표현식 연습!"을 출력하는 람다 표현식 생성 및 출력하기
		Test1 test2 = () -> {
			System.out.println("람다 표현식 연습!");
		};
		test2.testPrint();
		
		// 3. 정수 하나를 입력받아서 "입력한 숫자는 : 100"을 출력하는
		//		익명 클래스 생성 및 출력하기
		Test2 test3 = new Test2() {
			@Override
			public void testPrint(int n) {
				System.out.println("입력한 숫자는 : " + n);
			}
		};
		test3.testPrint(100);
		
		// 4. 정수 하나를 입력받아서 "입력한 숫자는 : 200"을 출력하는
		//		람다 표현식 생성 및 출력하기
		Test2 test4 = (n) -> {
			System.out.println("입력한 숫자는 : " + n);
		};
		test4.testPrint(200);
		
		
	} // end main()

} // end LambdaMain02







package edu.java.lambda03;

@FunctionalInterface
interface Test1 {
	public abstract void printMax(int x, int y);
} // end Test1

@FunctionalInterface
interface Test2 {
	public abstract int findMax(int x, int y);
} // end Test2

public class LambdaMain03 {

	public static void main(String[] args) {
		// 람다 표현식을 이용하여 구현
		Test1 test1 = (x, y) -> {
			int max;
			if(x > y) {
				max = x;
			} else {
				max = y;
			}
			System.out.println("최대값 : " + max);
		}; 
		test1.printMax(100, 101);
		
		Test2 test2 = (x, y) -> (x > y) ? x : y;
		System.out.println("최대값 : " + test2.findMax(10, 5));

	} // end main()

} // end LambdaMain03




package edu.java.exception01;

// 컴파일 에러 : 소스코드 빌드 시 발생하는 에러
// -> 실행 파일이 만들어지지 않기 때문에 실행할 수 없음
// 예외(Exception) : 
// -> 소스코드를 빌드할 때는 에러가 없지만,
// 	  프로그램을 수행할 때 발생하는 오류
// 논리적 오류 : 
// -> 컴파일 에러도 없고, 실행할 때 예외도 발생하지 않지만
//	  논리적인 문제 때문에 원하는 실행 결과가 나오지 않는 경우
public class ExceptionMain01 {

	public static void main(String[] args) {
//		int 123; // 컴파일 에러
		
//		int n = 123 / 0; 예외
		
		int result = findMax(20, 1);
		System.out.println(result);

	} // end main()
	
	public static int findMax(int x, int y) {
		if(x > y) {
			return x;
		} else {
			return y;
		}
	}

} // end ExceptionMain01
package edu.java.exception02;

import java.util.Scanner;

public class ExceptionMain02 {

	public static void main(String[] args) {
		System.out.println("예외 사례");
		
		Scanner sc = new Scanner(System.in);
		
//		int n1 = sc.nextInt();
//		int n2 = sc.nextInt();
//		
//		if(n2 != 0) {
//			int result = n1 / n2;
//			System.out.println("result = " + result);			
//		} else {
//			System.out.println("n2의 값이 0이 아닌 값을 입력하세요.");
//		}
		
		// 예외 처리 : try-catch 구문
		// - 예외 발생 상황에 대해 처리해주는 기능
		// try {
		//		정상적인 실행 문장들;
		// } catch (예외클래스 변수이름) {
		//		예외 상황일 때 실행할 문장들;
		// }
		
		try {
			System.out.println("try 내부");
			System.out.println("n3 입력>");
			int n3 = sc.nextInt();
			System.out.println("n4 입력>");
			int n4 = sc.nextInt();
			int result = n3 / n4;
			
			System.out.println("result = " + result);
		} catch (Exception e) {
			System.out.println("예외 발생 : " + e.toString());
		}
		System.out.println("프로그램 종료");
		sc.close();
		

	} // end main()

} // end ExceptionMain02
package edu.java.exception03;

public class ExceptionMain03 {

	public static void main(String[] args) {
		try {
			System.out.println("try 내부");
			int[] array = new int[10];
			array[13] = 100;
			System.out.println(array[10]);
		} catch (Exception e) { // 모든 예외 처리
			System.out.println("예외 메시지 : " + e.toString());
		}
		System.out.println("프로그램 종료");

	} // end main()

} // end ExceptionMain03
package edu.java.exception04;

public class ExceptionMain04 {

	public static void main(String[] args) {
		// Exception : 예외 처리를 위한 클래스
		// |_ ArithmeticException
		// |_ NullPointerException
		// |_ ...
		System.out.println("예외 메시지 출력");
		try {
			System.out.println("try 내부");
			String name = null;
			System.out.println("문자열 길이 : " + name.length());
		} catch (NullPointerException e) {
			System.out.println("예외 메시지 : " + e.toString());
		}
		System.out.println("프로그램 종료");
		
	} // end main()

} // end ExceptionMain04
package edu.java.exception05;

public class ExceptionMain05 {

	public static void main(String[] args) {
		// 하나의 try-catch 구문에서 여러 개의 catch를 사용하는 방법 1
		try {
			int x = 12345;
			int y = 0;
			int result = x / y;
			System.out.println("result = " + result);
			
			int[] array = new int[10];
			array[11] = 10;
			System.out.println("array[11] = " + array[11]);
			
			String name = null;
			System.out.println("문자열 길이 : " + name.length());
 		} catch (ArithmeticException e) { // e 변수에 예외에 대한 정보가 저장됨
 			System.out.println("산술연산 예외 : " + e.toString());
 		} catch (ArrayIndexOutOfBoundsException e) {
 			System.out.println("배열 인덱스 예외 : " + e.toString());			
		} catch (Exception e) {
			System.out.println("NullPointer 예외 : " + e.toString());
		}
		
		// 하나의 try 구문에서 여러 개의 catch를 사용하는 경우,
		// 자식 클래스의 Exception을 먼저 catch 구문에서 사용하고
		// 가장 마지막에 최상위 부모 클래스인 Exception을 사용해야함

	} // end main()

} // end ExceptionMain05
package edu.java.exception06;

public class ExceptionMain06 {

	public static void main(String[] args) {
		// 하나의 try 구문에서 여러 개의 catch를 사용하는 방법2 : Java 7 버전부터
		// try {
		// 		정상 상황일 때 사용할 코드;
		// } catch ( Ex1 | Ex2 | Ex3 | ... e) {
		// 		예외 상황일 때 실행할 코드
		// } catch (Exception e) { ... }
		try {
			System.out.println("try 시작");
			int result = 123 / 0;
			int[] array = new int[10];
			array[10] = 10;
			System.out.println("try 끝");
		} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
			System.out.println("예외 : " + e.toString());
		} catch (Exception e) {
			System.out.println("예외 : " + e.toString());
		}
		
	} // end main()

} // end ExcetionMain06
package edu.java.exception07;

import java.util.Scanner;

public class ExceptionMain07 {

	public static void main(String[] args) {
		System.out.println("try-catch-finally");
		// try { 
		//		정상적인 경우에 실행할 코드들;
		// } catch (Exception e) {
		// 		예외 상황일 때 실행할 코드;
		// } finally {
		//		정상적인 경우든, 예외 상황이든 상관없이 항상 실행할 코드
		// }
		
		Scanner sc = null;
		try {
			sc = new Scanner(System.in);
			int a = sc.nextInt();
			int b = sc.nextInt();
			int result = a / b;
			System.out.println("try 끝 : result = " + result);
		} catch (Exception e) {
			System.out.println("예외 : " + e.toString());
		} finally {
			System.out.println("finally : 언제 실행될까요?");
			sc.close();
		}
		System.out.println("프로그램 종료");
		
	} // end main()

} // end ExceptionMain07

package edu.java.exception08;

import java.util.Scanner;

public class ExceptionMain08 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		while(true) {
			try {
				System.out.println("메뉴 선택");
				int choice = Integer.parseInt(sc.next());
				System.out.println("choice : " + choice);
				break;
			} catch (Exception e) {
				System.out.println("숫자가 아닙니다. : ");
			}
		}

	} // end main()

} // ExceptionMain08

Thread사용

package edu.java.thread01;

// OS(운영체제) : 사용자의 하드웨어, 시스템 리소스를 제어하고
// 		프로그램에 대한 서비스를 지원하는 시스템 소프트웨어
//		 운영체제 종류 : Windows, Linux, Unix, MacOS
// 		프로세서 : 운영체제 내에서 연속적으로 실행되고 있는 프로그램
// 쓰레드(Thread) : 하나의 작업을 순차적으로 진행하는 실행 코드
// 멀티 쓰레드 프로그램 :
//  - 하나의 프로그램(프로세스)에서 여러 개의 쓰레드를 동작하는 프로그램
//  - 예) 채팅 프로그램 : 채팅 + 파일 전송

//자바에서 쓰레드를 생성하고 사용하는 방법1 :
//1. Thread 클래스를 상속받는 새로운 클래스 정의(extends Thread)
//2. 정의한 새로운 클래스 안에서 run() 메소드를 override
//-> run() : 쓰레드가 해야 할 기능 구현
//3. 정의한 클래스의 인스턴스를 생성
//4. 생성된 인스턴스에서 start() 메소드를 호출
//-> 쓰레드가 가져야 할 메모리 공간을 확보, 스케쥴링을 위해 쓰레드 등록, 초기화
//-> 쓰레드의 run() 메소드가 자동으로 실행됨

//1. Thread 클래스를 상속받는 새로운 클래스 정의(extends Thread)
class MyThread extends Thread {
	// 멤버 변수
	private String msg;

	// 생성자
	public MyThread(String msg) {
		this.msg = msg;
	}

	// 2. 정의한 새로운 클래스 안에서 run() 메소드를 override
	// -> run() : 쓰레드가 해야 할 기능 구현
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(i + " : " + msg);
			try {
				sleep(100); // 0.1초 동안 일을 멈춤(delay)
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
} // end MyThread
// 독립적인 존재가 같이 가기 때문에 순차적으로 출력되지 않는다.
public class ThreadMain01 {

	// 메인 함수도 쓰레드에서 동작 : 메인 쓰레드
	public static void main(String[] args) {
		// 3. Thread를 상속받는 클래스(MyThread)의 인스턴스 생성
		MyThread th1 = new MyThread("안녕");

		// 4. 생성된 인스턴스에서 start() 메소드를 호출 -> 쓰레드 실행
		th1.start();

		MyThread th2 = new MyThread("Hello");
		th2.start();

		System.out.println("<< 메인 쓰레드 종료 >>");
	} // end main()

} // end ThreadMain01

0개의 댓글