Java에서 별도의 스레드로 메서드를 호출하는 방법은 무엇입니까?


126

방법이 있다고 가정 해 봅시다 doWork(). 메인 스레드가 아닌 별도의 스레드에서 어떻게 호출합니까?


이 최근 관련 질문에 대한 몇 가지 예가 있습니다. 자바에서 무한 루프를 죽이는 것
Greg Hewgill

stackoverflow.com/questions/36832094/... 나는 비슷한 문제 PLS 날이 해결하는 데 도움이
Sruthi ACG

비동기 작업을위한 Reactive Java blog.danlew.net/2014/09/15/grokking-rxjava-part-1 을 살펴볼 수도 있습니다
Nathan Dunn

답변:


138

Runnable인터페이스 를 구현하는 클래스를 만듭니다 . 실행하려는 코드를 run()메소드 에 넣으십시오 Runnable. 이것이 인터페이스 를 준수하기 위해 작성해야하는 메소드입니다 . "기본"스레드에서 새 Thread클래스를 만들고 생성자에의 인스턴스를 전달한 Runnable다음 호출 start()합니다. startJVM에게 새 스레드를 만드는 마법을 수행 한 다음 run해당 새 스레드에서 메서드 를 호출하도록 지시합니다 .

public class MyRunnable implements Runnable {

    private int var;

    public MyRunnable(int var) {
        this.var = var;
    }

    public void run() {
        // code in the other thread, can reference "var" variable
    }
}

public class MainThreadClass {
    public static void main(String args[]) {
        MyRunnable myRunnable = new MyRunnable(10);
        Thread t = new Thread(myRunnable)
        t.start();
    }    
}

시작하려면 Java의 동시성 자습서 를 살펴보십시오 .

메서드가 자주 호출되는 경우 비용이 많이 드는 작업이므로 매번 새 스레드를 생성 할 가치가 없습니다. 일종의 스레드 풀을 사용하는 것이 가장 좋습니다. 한 번 봐 가지고 Future, Callable, Executor에서 클래스 java.util.concurrent패키지를.


1
전달하려는 변수가 있으면 어떻게합니까?
Louis Rhys

8
run()메서드는 매개 변수를 사용하지 않으므로 변수를 전달할 수 없습니다. 생성자에 전달하는 것이 좋습니다. 내 대답을 수정하여 표시합니다.
Noel M

1
다른 스레드에서 하나의 메서드를 호출하는 짧은 방법이 있습니까? new Thread() { public void run() {myMethod();}}.start();방법을 알아요 , 그게 가장 짧은가요?
Steven Roose 2012

@NoelM 당신과 MANN의 대답의 차이점을 설명해 주시겠습니까?
Asif Mushtaq 2015 년

2
MANN의 대답은 익명의 구현을 사용하는 Runnable광산 확장하는 클래스입니다 - Runnable. 그리고 인스턴스화 된 객체에 상태를 전달하는 자체 생성자가 있습니다.
Noel M

183
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        // code goes here.
    }
});  
t1.start();

또는

new Thread(new Runnable() {
     @Override
     public void run() {
          // code goes here.
     }
}).start();

또는

new Thread(() -> {
    // code goes here.
}).start();

또는

Executors.newSingleThreadExecutor().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

또는

Executors.newCachedThreadPool().execute(new Runnable() {
    @Override
    public void run() {
        myCustomMethod();
    }
});

이것은 내가하는 일에 완벽하게 작동했습니다. 관찰자 패턴을 사용하여 동시에 웹 서비스를 실행하고 진행률 표시 줄을 업데이트하는 데 필요합니다.
dpi

@Ashish : 편집 된 내용과 이유를 설명해주세요.
MANN 2014 년

1
@AshishAggarwal : 누군가가 저자의 허락을받지 않고 그렇게하면 나에게 이상해 보인다!
MANN

@MANN 스레드 매개 변수에서 실행 방법을 사용하는 이유를 설명 할 수 있습니까? 더 나은 성능?
Asif Mushtaq 2015 년

1
스레드를 명시 적으로 종료해야합니까? 스레드를 명시 적으로 종료하지 않으면 메모리 누수가 발생할 위험이 없습니까? 아니면 스레드가 완료되면 종료 run()됩니까?
theyuv

59

Java 8에서는 한 줄의 코드로이를 수행 할 수 있습니다.

메서드가 매개 변수를 사용하지 않는 경우 메서드 참조를 사용할 수 있습니다.

new Thread(MyClass::doWork).start();

그렇지 않으면 람다 식으로 메서드를 호출 할 수 있습니다.

new Thread(() -> doWork(someParam)).start();

다시 가져 와서 미안하지만 정확히 무엇을 ->의미합니까?
Kyle

1
이것이 람다 식을 만드는 데 사용되는 구문입니다. 자세한 정보는 다음 링크를 참조하십시오. Java에서 '->'는 무엇을합니까? 그리고 자바 (Java ™) 자습서 - 람다 표현식
아론 콘

@AaronCohn 좋은 물건 남자! Java 스레드에 대한 대안을 알고 있습니까? 나는 파이썬 세계에서 왔는데, 우리가 Celery task queue비동기적인 것들에 사용
하겠는가

Java는 스레드를 처리하기 위해 더 높은 수준의 추상화를 가지고 있지만 Akka 와 같은 것을 찾고있을 수도 있습니다 .
Aaron Cohn

8

사물을 호출하는 또 다른 빠른 옵션 (예 : DialogBoxes 및 MessageBoxes 및 스레드가 아닌 메서드를위한 별도의 스레드 생성)은 Lamba 표현식을 사용하는 것입니다.

  new Thread(() -> {
                      "code here"
            }).start();

3

얼마 전에 JDK5 실행기 서비스를 사용하고 백그라운드에서 특정 프로세스를 실행하는 간단한 유틸리티 클래스를 작성했습니다. doWork ()는 일반적으로 void 반환 값을 가지므로이 유틸리티 클래스를 사용하여 백그라운드에서 실행할 수 있습니다.

이 유틸리티를 문서화 한이 기사를 참조하십시오 .


6
Future and Callable은 당신을 위해 이런 일을합니다.
Amir Afghani

네, 그렇습니다. 여기서 아이디어는 비동기 래퍼 뒤의 인터페이스를 추상화하는 것입니다.
raja kolluru 2010 년

링크가 끊어졌습니다 (404).
palacsint

3

RxJava 2.x로이를 달성하려면 다음을 사용할 수 있습니다.

Completable.fromAction(this::dowork).subscribeOn(Schedulers.io().subscribe();

subscribeOn()메서드는 작업을 실행할 스케줄러를 지정합니다. RxJava에는 Schedulers.io()I / O 작업을위한 스레드 풀과 Schedulers.computation()CPU 집약적 인 작업을위한 스레드 풀을 포함하여 미리 정의 된 여러 스케줄러 가 있습니다.


3

Java 8 이상을 사용하는 경우 CompletableFuturerunAsync 클래스의 메소드 를 사용할 수 있습니다.

CompletableFuture.runAsync(() -> {...});

결과를 반환해야하는 경우 supplyAsync대신 사용

CompletableFuture.supplyAsync(() -> 1);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.