Java 쓰레드 구현
Java의 일반 쓰레드 구현 방식은 다음과 같다.
- Thread 클래스를 상속한 클래스의 객체를 생성과 동시에 구동
- Thread 클래스를 상속한 클래스의 객체를 생성한 후 나중에 구동
- Runnable 인터페이스를 구현한 클래스의 객체를 생성과 동시에 구동
- Runnable 인터페이스를 구현한 클래스의 객체를 생성한 후 나중에 구동
- 4번을 inline으로 구현하기
- 4번을 anonymous로 구현하기
- 4번을 Lambda로 구현하기
4번째가 가장 많이 사용되는 방식이다. 그 이유는 다음과 같다.
- 쓰레드 관련 코드와 테스크 관련 코드의 구현이 분리된다.
- 쓰레드 생성과 실행 등의 제어가 더 용이하다.
5, 6, 7번째의 경우에는 테스트를 별도 클래스가 아닌 함수로 구현하기 때문에 사용할 때 제약이 있다. 대신 UI 이벤트 처리등에 많이 사용된다.
1. Thread 객체를 만들자 마자 실행하는 경우
Thread 클래스를 상속하여 쓰레드를 구현할 때는 3가지만 생각하면 된다.
- Thread class를 상속
- public void run()을 구현
- start()로 run() 메소드를 호출
package S_20210201;
import java.util.concurrent.TimeUnit;
public class FirstWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
new MyThreadTask();
Thread mt = new MyThreadTask();
System.out.println("Main Thread Ends ...");
}
}
class MyThreadTask extends Thread{
private static int count = 0;
private int id;
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("<"+id+"> LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public MyThreadTask() {
this.id=count++;
this.start();
}
}
결과
2. Thread 객체를 원하는 시점에 실행하는 경우
run() 메소드를 호출을 Thread 객체를 받는 변수에서 호출하는 것이다.
package S_20210201;
import java.util.concurrent.TimeUnit;
public class SecondWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
new MyThreadTask1().start();;
Thread mt = new MyThreadTask1();
mt.start();
System.out.println("Main Thread Ends ...");
}
}
class MyThreadTask1 extends Thread{
private static int count = 0;
private int id;
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("<"+id+"> LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public MyThreadTask1() {
this.id=count++;
// this.start();
}
}
결과는 위와 동일하다.
3. Runnable 객체를 만들자 마자 실행하는 경우
Runnable 인터페이스를 이용해 쓰레드를 구동할 때는 3가지만 생각하면 된다.
- Runnable 인터페이스 구현
- public void run()을 구현
- Thread(Runnable) 객체를 만들어 start()로 run() 메소드를 호출
package S_20210201;
import java.util.concurrent.TimeUnit;
public class ThirdWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
new MyThreadTask2();
new MyThreadTask2();
System.out.println("Main Thread Ends ...");
}
}
class MyThreadTask2 implements Runnable{
private static int count = 0;
private int id;
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("<"+id+"> LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public MyThreadTask2() {
this.id=count++;
new Thread(this).start();
}
}
결과는 위와 동일하다.
4. Runnable 객체를 원하는 시점에 실행하는 경우
run() 메소드를 호출을 Runnable 레퍼런스에서 호출하는 것이다.
package S_20210201;
import java.util.concurrent.TimeUnit;
public class FourthWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
new Thread(new MyThreadTask3()).start();
Thread tr = new Thread(new MyThreadTask3());
tr.start();
System.out.println("Main Thread Ends ...");
}
}
class MyThreadTask3 implements Runnable{
private static int count = 0;
private int id;
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("<"+id+"> LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public MyThreadTask3() {
this.id=count++;
// new Thread(this).start();
}
}
결과는 위와 동일하다.
5. Runnable 을 inline으로 구현하기
다음은 Runnable를 별도의 클래스 없이 inline 으로 구현한 것이다. 주로 UI 이벤트 등의 처리에 많이 사용한다.
package S_20210201;
import java.util.concurrent.TimeUnit;
public class FifthWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
Runnable myThreadTask4 = new Runnable() {
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Thread tr = new Thread(myThreadTask4);
tr.start();
System.out.println("Main Thread Ends ...");
}
}
6. inline Runnable을 Anonymous로 구현
UI event등의 처리에 많이 사용되는 방식
package S_20210201;
import java.util.concurrent.TimeUnit;
public class SixthWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<5;i++) {
System.out.println("LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
System.out.println("Main Thread Ends ...");
}
}
결과는 위와 동일하다.
7. Runnable Lambda로 구현하기
위의 6번째를 Lambda로 구현한 것이다.
package S_20210201;
import java.util.concurrent.TimeUnit;
public class SeventhWay{
public static void main(String[] args) throws Exception {
System.out.println("Main Thread Starts ...");
new Thread(()->{
for(int i=0;i<5;i++) {
System.out.println("LoopCnt = "+i);
try {
TimeUnit.MICROSECONDS.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
System.out.println("Main Thread Ends ...");
}
}
결과는 위와 동일하다.
참고 블로그 : http://hochulshin.com/java-multithreading-thread-thread-implementation/
'JAVA > 쓰레드' 카테고리의 다른 글
[쓰레드] 프로세스와 쓰레드 차이 (0) | 2021.04.12 |
---|---|
[JAVA 쓰레드 #5] 데몬 쓰레드 (0) | 2021.02.03 |
[JAVA 쓰레드 #4] 쓰레드에서 값 반환 (0) | 2021.02.02 |
[JAVA 쓰레드 #3] 쓰레드 이름 설정 (0) | 2021.02.01 |
[JAVA 쓰레드 #2] Executor 기본 (0) | 2021.02.01 |