여러 스레드를 가진다
= 병렬적으로 작업을 할 수 있다는 것
= 한 번에 여러 작업 가능
=> 멀티 태스킹
run()
메서드에다가 스레드가 실행할 코드를 작성해야 한다.run()
메서드는 Runnable 인터페이스와 Thread 클래스에 정의되어져 있다.// Runnable 인터페이스가 run 메서드를 강제
public interface Runnable {
public abstract void run();
}
// Thread 클래스는 Runnable 인터페이스를 구현함
class Thread implements Runnable{
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new ThreadTask1());
}
}
class ThreadTask1 implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("#");
}
}
}
public class Main {
public static void main(String[]args) {
// Thread 클래스를 상속받은 클래스를 인스턴스화하여 스레드를 생성
ThreadTask2 thread2 = new ThreadTask2();
}
}
class ThreadTask2 extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("#");
}
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new ThreadTask1());
thread.start();
}
}
start()
메소드를 통해서, 스레드를 실행 대기
상태로 바꿔준다.
실제로 스레드를 실행시켜 주는 것은 운영체제의 스케쥴러이다.
출처: https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=qbxlvnf11&logNo=220921178603
스레드가 동일한 데이터를 공유하게 되면서 문제가 발생한다.
한 스레드가 코드를 실행할 때, 다른 스레드가 그 과정에 끼어들어 작업을 하게 되면 이것저것이 꼬이기 때문이다.
이런 문제가 발생하지 않도록 하는 것이 스레드 동기화
이고, 이때 임계 영역
과 락
을 사용한다.
스레드 A는 임계 영역을 포함한 객체에 대한 락을 얻어, 임계 영역 내의 코드를 실행한다.
이때 스레드 A를 제외한 다른 스레드는 락이 없기 때문에, 해당 임계 영역에 접근할 수 없다.
스레드 A가 락을 반납하면, 다른 스레드 중 하나가 락을 획득하여 임계 영역 내의 코드를 실행하게 된다.
synchronized
키워드를 통해, 임계 영역을 설정한다.