스레드와 JVM에 대해 배웠다.
스레드 개념은 대충 알겠는데, 얘네를 활용하라고 하면 잘 못하겠어
특히 관련 메서드들. 얘네가 하는 일이 정확히 뭔지 아직 잘 모르겠다.
공식 문서나 다시 읽자...
프로세스 : 운영체제에서 필요한 메모리를 할당받아 실행중인 애플리케이션.
스레드 : 프로세스에서 실행되는 소스 코드의 실행 흐름
여지껏 작성한 코드들은 싱글 스레드
메인 스레드 : main 메서드를 실행시키는 스레드
멀티 스레드 프로세스는 메인 스레드에서 추가적으로 스레드를 생성하여 실행.
자바에서는 run()이라는 메서드가 스레드가 처리 작업을 작성하도록 되어있다.
run()은 Runnable 인터페이스를 구현한 객체에서 run()을 구현할 수도 있고,
Thread의 하위 클래스에서 구현할 수도 있다.
package test01;
public class test {
public static void main(String[] args) {
Runnable task = new ThreadTask();
Thread thread = new Thread(task);
thread.start();
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
}
}
class ThreadTask implements Runnable{
//class ThreadTask extends Thread 이후 ThreadTask의 인스턴스 변수의 start()로도 멀티스레드로 실행할 수 있다.
@Override
public void run() {
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
}
}
/*
1111111111
1111111111
1111111111
1111111111
1111111111
1111111111
1111111111
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
1111111111
1111111111
1111111111
*/
package test01;
public class test {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
//익명 구현 객체로도 가능하다
@Override
public void run() {
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
System.out.println("0000000000");
}
});
thread.start();
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
System.out.println("1111111111");
}
}
메인스레드의 이름은 main
추가 생성되 스레드의 디폴트 이름은 Thread-n
스레드의 이름은 thread.getName()으로 알 수 있다
스레드의 이름은 thread.setName()으로 바꿀 수 있다
현재 실행중인 스레드의 주소값은 Thread 클래스의 정적 메서드 currentThread(), 즉 Thread.currentThread().getName()으로 알 수 있다.
스레드 동기화 : 서로 다른 스레드가 같은 데이터를 공유하여 생기는 문제를 방지하기 위해 사용한다.
메서드의 접근자로 synchronized를 붙이거나 메서드 내에서 synchronized(this)를 사용한다.
package test02;
public class test {
public static void main(String[] args) {
Runnable thread = new testCase();
Thread thread1 = new Thread(thread);
Thread thread2 = new Thread(thread);
thread1.setName("caseA");
thread2.setName("caseB");
thread1.start();
thread2.start();
}
}
class testCase implements Runnable{
int num = 5;
@Override
public void run() {
while (true) {
if (num < 0) {
System.out.println(Thread.currentThread().getName() + ":done");
break;
}
else {
System.out.println(Thread.currentThread().getName() + ":" + num--);
}
}
}
}
/*
동기화를 하지 않을 경우!!1
caseA:4
caseB:5
caseA:3
caseB:2
caseA:1
caseB:0
caseB:done
caseA:done
caseA, B에 동시에 접근한다
*/
package test02;
public class test {
public static void main(String[] args) {
Runnable thread = new testCase();
Thread thread1 = new Thread(thread);
Thread thread2 = new Thread(thread);
thread1.setName("caseA");
thread2.setName("caseB");
thread1.start();
thread2.start();
}
}
class testCase implements Runnable{
int num = 5;
@Override
public void run() {
synchronized (this){
while (true) {
if (num < 0) {
System.out.println(Thread.currentThread().getName() + ":done");
break;
}
else {
System.out.println(Thread.currentThread().getName() + ":" + num--);
}
}
}
}
}
/*
동기화를 적용한 경우
caseA:5
caseA:4
caseA:3
caseA:2
caseA:1
caseA:0
caseA:done
caseB:done
*/
스레드의 상태는
NEW : 생성
RUNNABLE : 실행 대기
WAITING, TIMED_WAITING, BLOCKED
TERMINATED : 실행 이후 소멸
로 나눌 수 있다
start() : 스레드를 실행 대기 상태로 옮긴다
sleep(long ms) : 스레드를 잠시 멈춘다(TIMED_WAITING)
ms만큼 시간이 지나거나, interrupt()를 호출한다면 runnable로 복귀한다
interrupt() : 일시 정지에 있는 스레드를 runnable로 옮긴다
interrupt는 예외가 발생하므로 예외 처리를 해주어야한다.
yield() : 다른 스레드에 실행을 양보한다
join() : 다른 스레드의 작업이 끝날 때까지 기다린다