Java Thread
Java Thread
Java 프로그램에서 스레드를 생성하는 기법에는 두 가지가 있다.
한 가지 방법은 Thread 클래스로부터 파생된 새로운 클래스를 생성하고, Thread 클래스의 run() 메소드를 무효화(override)하는 것이다.
다른 방법은 더 흔히 사용되는 방법으로서 Runnable 인터페이스를 구현하는 클래스를 정의하는 것이다.
Thread 클래스
public class Test extends Thread {
int seq;
public Test(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(this.seq + " thread start");
try{
Thread.sleep(1000);
}catch(Exception e) {}
System.out.println(this.seq + " thread end")
}
public static void main(String[] args) {
ArrayList<Thread> threads = new ArrayList<Thread>();
for(int i=0; i<10; i++){
Thread t = new Test(i);
t.start();
threads.add(t);
}
for(int i=0; i<threads.size(); i++) {
Thread t = threads.get(i);
try{
t.join();
}catch(Exception e) {}
}
System.out.println("main end");
}
}
test.start() 실행 시 test 객체의 run 메소드가 실행된다.
Thread 클래스는 start 실행 시 run 메소드가 수행되기 때문에, Thread를 상속한 Test 클래스의 객체 또한 그렇다.
생성되는 스레드를 담기 위해서 ArrayList threads를 만들고 생성된 객체들을 이에 저장한다.
join 메소드는 스레드가 종료될 때까지 기다리게 하는 메소드이다.
main이 종료되기 전에 각각의 join을 호출하여 스레드 종료까지 대기한다.
Runnable
public interface Runnable {
public abstract void run(); // abstract란 추상 메소드로
// 메소드의 시그니처만이 정의된 비어있는 메소드이다.
}
abstract를 붙임으로써 상속을 통하여 구현해야 됨을 알 수 있다.
추상메소드는 선언부와 구현부로 구성되어 있는데, 선언부만 작성하고 구현부는 작성하지 않고 남겨 둔다.
상속받는 클래스에 따라 구현부를 다르게 작성한다.
Runnable을 구현할 때 run() 메소드를 구현하는 코드는 별도의 스레드로서 실행된다.
다음은 음이 아닌 정수의 합을 결정하는 다중 스레드 프로그램이다.
class Sum {
private int sum;
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
}
class Summation implements Runnable {
private int upper;
private Sum sumValue;
public Summation(int upper, Sum sumValue) {
this.upper = upper;
this.sumValue = sumValue;
}
public void run() {
int sum = 0;
for (int i = 0; i <= upper; i++)
sum += i;
sumValue.setSum(sum);
}
}
public class Driver
{
public static void main(String[] args) {
if (args.length > 0) {
if (Interger.parseInt(args[0]) < 0)
System.err.println(args[0] + " must be >= 0.");
else {
Sum sumObject = new Sum();
int upper = Integer.parseInt(args[0]);
Thread thrd = new Thread(new Summation(upper, sumObject));
thrd.start();
try {
thrd.join();
System.out.println("The sum of " + upper + " is " + sumObject.getSum());
} catch (InterruptedException ie) {}
}
}
else
System.err.println("m of " + upper + " is " + sumObject.get());
}
}
합 프로그램이 실행될 때 JVM은 두 개의 스레드를 생성한다.
첫 번째 스레드는 부모 스레드이고 main() 메소드에서 실행을 시작한다.
두 번째 스레드는 Thread 객체의 start() 메소드가 호출될 때 생성된다.
이 자식 스레드는 Summation 클래스의 run() 메소드에서 실행을 시작한다.
이 합의 결과를 출력한 뒤 이 스레드는 run() 메소드를 빠져나올 때 종료한다.
새로운 sum 클래스를 정의하는 이유는 Integer 클래스는 한 번 지정되면 그 값을 변경할 수 없기 때문이다.
main 스레드와 합 스레드가 Sum 클래스의 객체 인스턴스를 공유한다.
이 공유 객체는 getSum()과 setSum() 메소드를 통하여 참조된다.