실행 중인 어플리케이션
데이터와 어플리케이션이 확보한 자원을 활용하여 소스 코드를 실행 -> 하나의 코드 실행 흐름
public class ProducingThread {
public static void main(String[] args) {
// Runnable task1 = new TheadTask1();
// Thread thread1 = new Thread(task1);
// 아래의 코드로 축약 가능
// Runnable 인터페이스 구현한 객체에서 thread 생성
Thread thread1 = new Thread(new ThreadTask1());
// Runnable 익명 객체에서 thread 생성
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("2");
}
}
});
// Thread 클래스를 상속받은 하위 클래스에서 thread 생성
Thread thread3 = new ThreadTask2();
// Thread 익명 하위 객체를 통한 thread 생성
Thread thread4 = new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("4");
}
}
};
thread1.start();
thread2.start();
thread3.start();
thread4.start();
for (int i = 0; i < 100; i++) {
System.out.print("@");
}
}
}
class ThreadTask1 implements Runnable {
public void run(){
for (int i = 0; i < 100; i++) {
System.out.print("1");
}
}
}
class ThreadTask2 extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("3");
}
}
}
public class NameOfThread {
public static void main(String[] args) {
Thread exampleThread = new Thread() {
public void run() {
System.out.println("Thread running");
}
};
exampleThread.start();
System.out.println("exampleThread.getName() = " + exampleThread.getName());;
exampleThread.setName("Hello");
System.out.println("exampleThread.getName() = " + exampleThread.getName());
// Thread.currentThread() : 현재 실행중인 thread의 주소값에 접근
System.out.println(Thread.currentThread().getName());
}
}
출력
Thread running
exampleThread.getName() = Thread-0
exampleThread.getName() = Hello
main
하나의 스레드만 코드를 실행 할 수 있는 영역
블록 안 코드로 진입할때 해당 코드를 실행하고 있는 스레드가 락을 얻음
임계 영역을 포함한 객체에 접근할 수 있는 권한
public class SynchronizeTest {
public static void main(String[] args) {
// Thread thread1 = new Thread(new ThreadTask());
// Thread thread2 = new Thread(new ThreadTask());
// -> thread1, 2가 각각의 ThreadTask 객체를 가지고 실행됨
Runnable threadTask = new ThreadTask();
Thread thread1 = new Thread(threadTask);
Thread thread2 = new Thread(threadTask);
// -> thread1, 2가 하나의 ThreadTask 객체를 공유
thread1.setName("춘식");
thread2.setName("봉남");
thread1.start();
thread2.start();
}
}
class Account {
private int balance = 1000;
public int getBalance() {
return balance;
}
public synchronized boolean withdraw (int money) {
if (money <= balance) {
try { Thread.sleep(1000); } catch (Exception error){}
balance -= money;
return true;
}
return false;
}
}
class ThreadTask implements Runnable {
Account account = new Account();
public void run() {
while (account.getBalance() > 0) {
int money = (int) (Math.random() * 3 + 1) * 100;
boolean denied = !account.withdraw(money);
System.out.println(String.format("Withdraw %d₩ By %s. Balance : %d %s",
money, Thread.currentThread().getName(), account.getBalance(), denied ? "=> DENIED" : "")
);
}
}
}
출력
Withdraw 200₩ By 춘식. Balance : 800
Withdraw 300₩ By 봉남. Balance : 500
Withdraw 200₩ By 춘식. Balance : 300
Withdraw 200₩ By 봉남. Balance : 100
Withdraw 100₩ By 봉남. Balance : 0 => DENIED
Withdraw 100₩ By 춘식. Balance : 0
임계영역 지정을 안했을때
Withdraw 300₩ By 춘식. Balance : 700
Withdraw 200₩ By 봉남. Balance : 700
Withdraw 300₩ By 봉남. Balance : 400
Withdraw 100₩ By 춘식. Balance : 300
Withdraw 300₩ By 춘식. Balance : -300
Withdraw 300₩ By 봉남. Balance : -300
milliSecond 동안 스레드를 멈춤
일시 중지 상태인 스레드를 실행 대기 상태로 복귀
public class ThreadStateTest {
public static void main(String[] args) {
Thread thread = new Thread() {
public void run() {
try {
while (true) Thread.sleep(1000);
}
catch (Exception e) {}
System.out.println("woke up");
}
};
System.out.println("thread.getState() = " + thread.getState());
// thread.getState() = NEW
thread.start();
System.out.println("thread.getState() = " + thread.getState());
// thread.getState() = RUNNABLE
while (true) {
if (thread.getState() == Thread.State.TIMED_WAITING) {
System.out.println("thread.getState() = " + thread.getState());
// thread.getState() = TIMED_WAITING
break;
}
}
// sleep 중인 thread에 예외 발생 -> catch문 실행 후 실행 대기 상태
thread.interrupt();
// woke up
while (true) {
if (thread.getState() == Thread.State.RUNNABLE) {
System.out.println("thread.getState() = " + thread.getState());
// thread.getState() = RUNNABLE
break;
}
}
while (true) {
if (thread.getState() == Thread.State.TERMINATED) {
System.out.println("thread.getState() = " + thread.getState());
// thread.getState() = TERMINATED
break;
}
}
}
}
스케줄러에 의해 할당받은 실행시간을 다른 스레드에 양보
public void run() {
while (true) {
if (example) {
... // 무의미한 반복을 멈추고 실행 대기상태로 바뀜
}
else Thread.yield();
}
}
다른 스레드의 작업이 끝날 때까지 기다림
public class joinTest {
public static void main(String[] args) {
SumThread sumThread = new SumThread();
sumThread.setTo(10);
sumThread.start();
// main 스레드가 sumThread의 작업이 끝날 때까지 대기
// 주석 처리시 출력 : 1부터 10까지의 합 = 0
try { sumThread.join(); } catch (Exception e) {}
System.out.println(String.format("1부터 %d까지의 합 = %d", sumThread.getTo(), sumThread.getSum()));
}
}
class SumThread extends Thread {
private long sum;
private int to;
public long getSum() {
return sum;
}
public int getTo() {
return to;
}
public void setTo(int to) {
this.to = to;
}
@Override
public void run() {
for (int i = 0; i <= to; i++) {
sum += i;
}
}
}
스레드 간 협업에 사용
public class Wait_NotifyTest {
public static void main(String[] args) {
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 < 5; 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 < 5; i++) {
workObject.methodB();
}
}
}
출력
ThreadA의 methodA Working
ThreadB의 methodB Working
ThreadA의 methodA Working
ThreadB의 methodB Working
ThreadA의 methodA Working
ThreadB의 methodB Working
ThreadA의 methodA Working
ThreadB의 methodB Working
ThreadA의 methodA Working
ThreadB의 methodB Working
Last In First Out
JVM 작동시 영역 자동 생성
프로그램에서 더 이상 사용하지 않는 객체를 찾아 제거하여 메모리를 확보
Heap Area의 Young의 가비지 컬렉터는 Minor GC
Old의 가비지 컬렉터는 Magor GC