두 가지 이상의 작업을 동시에 처리하는 것
멀티 프로세스 : 독립적으로 프로그램들을 실행하고 여러 작업 처리 (애플리케이션 단위의 멀티 태스킹)
멀티 스레드 : 한 개의 프로그램을 실행하고 내부적으로 여러 가지 작업 처리 (ex, 미디어 플레이어가 동영상 재생과 음악 재생을 동시에 처리)
(애플리케이션 내부의 멀티 태스킹)
main()메소드의 첫 코드부터 아래로 순차적으로 실행, 마지막 코드를 실행하거나 return문을 만나면 실행이 종료
필요에 따라 작업 스레드들을 만들어서 병렬로 코드를 실행할 수 있음
메인 스레드가 작업 스레드보다 먼저 종료되더라도 작업 스레드가 계속 실행 중이라면 프로세스는 종료되지 않음
class SampleRunnable implements Runnable {
int seq;
public SampleRunnable(int seq) {
this.seq = seq;
}
@Override
public void run() {
System.out.println(seq + " runnable start");
try {
int sleepcount = ((int)(Math.random() * 2) + 1) * 1000;
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(seq + " runnable end");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("start");
//st.run();
for (int i = 1; i <= 10; i++) {
// Runnable 인터페이스 구현 객체
SampleRunnable sr = new SampleRunnable(i);
// Thread에 runnable target을 매개변수로 받는 생성자를 불러옴
Thread th = new Thread(sr);
// 스레드 생성 호출
th.start();
// start는 없고 run으로 실행
// 이렇게 부르면 그 자체로 스레드가 되지 않기 때문에 의도한 것처럼 멀티 스레드가 아닌 단일 스레드처럼 작동한다
// sr.run();
}
System.out.println("end");
}
class SampleThread extends Thread {
int seq;
public SampleThread(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(seq + " start");
try {
int sleepcount = ((int)(Math.random() * 2) + 1) * 1000;
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
// 스레드 1초동안 잠깐 자고 있어
System.out.println(seq + " end");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Thread> threadList = new ArrayList<Thread>();
System.out.println("main start");
for (int i = 1; i<=10; i++) {
Thread th = new SampleThread(i);
// 스레드 생성 및 시작
// Thread를 상속받아서 만들어졌기 때문에 부모 클래스인 Thread가 가지고 있는 start 메소드를 실행할 수 있음
th.start();
threadList.add(th);
}
for (int i = 0; i<threadList.size(); i++) {
try {
// main end가 제일 마지막에 끝남
threadList.get(i).join(); // 쓰레드 끝나는거 대기 (기다리기)
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("main end");
}
결과
+++
public class TestMain2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
// Thread를 상속받아서 만든 자식클래스인 threadclass
Threadclass s1 = new Threadclass();
1 s1.run(); 출 O / 스레드생성 X
2 s1.start(); 출력 O / 스레드생성 O
// 부모 타입의 객체에 담아둔 자식 타입 클래스 threadclass
Thread s2 = new Threadclass();
3 s2.run(); 출 O / 스레드생성 X
4 s2.start(); 출 O / 스레드생성 O
// thread 그 자체
Thread s3 = new Thread();
5 s3.run(); 출력 X (재정의한게 없어) / 스레드생성 X
6 s3.start(); 출력 X (재정의한게 없어) / 스레드생성 O (생성은 되는데 부를게 없어)
Runclass s4 = new Runclass();
7 s4.run(); 출력 O (run 메서드 있어) / 스레드 생성 X
8 s4.start(); x / x (start 자체를 부르지도 못하고 생성도 안됨)
Thread s5 = new Thread(new Runclass());
9 s5.run(); 스레드 안에 runnable 인터페이스를 구현한 객체 / 출력 O 스레드생성 X
10 s5.start(); 출력 O / 스레드생성 O
스레드여야 start를 부를 수 있고 start를 통해서 멀티 스레드를 생성할 수 있다?
runnable 인터페이스를 구현한 객체를 run 메소드만 재정의했을 뿐 그 자체로 스레드라고 할 수 없어서
start를 호출할 수도 없고 Thread 객체 안에 runnable target을 매개변수로 받는 생성자를 호출해야
거기에서 start를 호출해서 스레드도 생성할 수 있다
*/
}
}
class Threadclass extends Thread {
public void run() {
System.out.println("threadclass");
}
}
class Runclass implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("runclass");
}
}