1.스레드
2.스레드 동기화
3.예외처리
4.JVM
main
메서드이며, 메인 스레드가 main
메서드를 실행시켜준다.run()
메서드 내에 스레드가 처리할 작업을 작성run()
메서드는 Runnable 인터페이스와 Thread 클래스에 정의되어져 있다.Runnable
인터페이스를 구현한 객체에서 run()
을 구현하여 스레드를 생성하고 실행하는 방법
public class ThreadExample1 {
public static void main(String[] args) {
// Runnable 인터페이스를 구현한 객체 생성
Runnable task1 = new ThreadTask1();
// Runnable 구현 객체를 인자로 전달하면서 Thread 클래스를 인스턴스화하여 스레드를 생성
Thread thread1 = new Thread(task1);
// 위의 두 줄을 아래와 같이 한 줄로 축약 가능
// Thread thread1 = new Thread(new ThreadTask1());
// start() 메서드를 통해 run()메서드 내부의 코드 실행
thread1.start();
//반복문 추가
for (int i = 0; i < 100; i++) {
System.out.print("@");
}
}
}
// Runnable 인터페이스를 구현하는 클래스
class ThreadTask1 implements Runnable {
// run() 메서드 바디에 스레드가 수행할 작업 내용 작성
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("#");
}
}
}
// 익명 Runnable 구현 객체를 활용하여 스레드 생성
Thread thread1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("#");
}
}
});
thread1.start();
for (int i = 0; i < 100; i++) {
System.out.print("@");
}
}
}
Thread
클래스를 상속 받은 하위 클래스에서 run()
을 구현하여 스레드를 생성하고 실행하는 방법
public class ThreadExample2 {
public static void main(String[] args) {
// Thread 클래스를 상속받은 클래스를 인스턴스화하여 스레드를 생성
Thread thread2 = new ThreadTask2();
// 작업 스레드를 실행시켜, run() 내부의 코드를 처리
thread2.start();
// 반복문 추가
for (int i = 0; i < 100; i++) {
System.out.print("@");
}
}
}
// Thread 클래스를 상속받는 클래스 작성
class ThreadTask2 extends Thread {
// run() 메서드 바디에 스레드가 수행할 작업 내용 작성
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("#");
}
}
스레드의_참조값.getName()
으로 조회스레드의_참조값.setName()
으로 설정currentThread()
Thread.currentThread().getName()
Thread.sleep(1000);
try { … } catch ( ~ ) { … }
try
의 블록 내의 코드를 실행하다가 예외 또는 에러가 발생하면 catch
문의 블럭에 해당하는 내용을 실행synchronized
키워드 사용// 1. 메서드 전체를 임계 영역으로 지정
// 반환 타입 좌측에 synchronized 키워드를 작성
public synchronized boolean withdraw(int money) {
if (balance >= money) {
try { Thread.sleep(1000); } catch (Exception error) {}
balance -= money;
// 2. 특정한 영역을 임계 영역으로 지정
// synchronized 키워드와 함께 소괄호(()) 안에 해당 영역이 포함된 객체의 참조를 넣고, 중괄호({})로 블럭을 열어, 블럭 내에 코드를 작성
public boolean withdraw(int money) {
synchronized (this) {
if (balance >= money) {
try { Thread.sleep(1000); } catch (Exception error) {}
balance -= money;
start()
는 스레드를 실행시키는 메서드는 아니라, 실행대기 상태로 만들어주는 메서드다.실행
상태에서 일시 정지(TIMED_WAITING)
상태로 전환static void sleep(long milliSecond)
interrupt()
를 호출한 경우interrupt()
가 호출되면 기본적으로 예외가 발생하기 때문에 try … catch
sleep()
, wait()
, join()
에 의해 일시 정지
상태에 있는 스레드들을 실행 대기
멈춰 있는 스레드.interrupt()
를 호출하면, 기존에 호출되어 스레드를 멈추게 했던 sleep()
, wait()
, join()
메서드에서 예외가 발생되며, 그에 따라 일시 정지가 풀리게 된다.yield()
를 호출하면 남은 실행 시간 2초는 다음 스레드에게 양보static void yield()
일시 중지
상태로 만드는 상태 제어 메서드interrupt()
가 호출되거나, join()
호출 시 지정했던 다른 스레드가 모든 작업을 마치면 다시 실행 대기
상태로 복귀void join()
void join(long milliSecond)
sleep()
은 Thread 클래스의 static
메서드 Thread.sleep(1000);
join()
은 특정 스레드에 대해 동작하는 인스턴스 메서드 thread1.join();
스레드A가 공유 객체에 자신의 작업을 완료 → 스레드B와 교대하기 위해 notify()
를 호출 notify()
가 호출되면 스레드B가 실행 대기
상태가 되며, 곧 실행
스레드A는 wait()
을 호출하며 자기 자신을 일시 정지
상태로 만든다.
WorkObject sharedObject = new WorkObject();
ThreadA threadA = new ThreadA(sharedObject);
ThreadB threadB = new ThreadB(sharedObject);
threadA.start();
threadB.start();
}
}
class WorkObject {
public synchronized void methodA() {
System.out.println("ThreadA의 methodA Working");
notify();
try { wait(); } catch(Exception e) {}
}
public synchronized void methodB() {
System.out.println("ThreadB의 methodB Working");
notify();
try { wait(); } catch(Exception e) {}
}
}
class ThreadA extends Thread {
private WorkObject workObject;
public ThreadA(WorkObject workObject) {
this.workObject = workObject;
}
public void run() {
for(int i = 0; i < 10; i++) {
workObject.methodA();
}
}
}
class ThreadB extends Thread {
private WorkObject workObject;
public ThreadB(WorkObject workObject) {
this.workObject = workObject;
}
public void run() {
for(int i = 0; i < 10; i++) {
workObject.methodB();
}
}