답변:
생성자의 매개 변수를 Runnable 객체로 전달해야합니다.
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
다음과 같이 호출하십시오.
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
r
는 동일한 인수를 가지므로 실행중인 여러 스레드에 다른 인수를 전달 MyThread
하려면 MyThread
각 스레드에 대해 원하는 인수를 사용하여 새 인스턴스 를 만들어야합니다 . 다시 말해, 스레드를 시작하고 실행하려면 Thread와 MyThread라는 두 개의 개체를 만들어야합니다. 이것이 성능 측면에서 나쁜 것으로 간주됩니까?
질문 편집에 대한 응답으로 익명 클래스에서 작동하는 방식은 다음과 같습니다.
final X parameter = ...; // the final is important
Thread t = new Thread(new Runnable() {
p = parameter;
public void run() {
...
};
t.start();
Thread를 확장하거나 Runnable을 구현하는 클래스와 전달하려는 매개 변수가있는 생성자가 있습니다. 그런 다음 새 스레드를 만들 때 인수를 전달한 다음 다음과 같이 스레드를 시작해야합니다.
Thread t = new MyThread(args...);
t.start();
Runnable은 Thread BTW보다 훨씬 나은 솔루션입니다. 그래서 선호합니다 :
public class MyRunnable implements Runnable {
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void run() {
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
이 답변은 기본적 으로이 비슷한 질문과 동일합니다 : Thread 객체에 매개 변수를 전달하는 방법
parameter
에서 직접 액세스한다는 점을 제외하고는 익명 클래스 예제와 유사한 코드가 있습니다 . 작동하는 것 같습니다. 내가 복사하지 않음으로써 실종 미묘한 멀티 스레딩 일이 있는가 하는 사전은? run()
p
parameter
p
)
첫 번째 예제에서 빠진 것 같아요
final X parameter
전과 new Runnable()
라인, 그때에 액세스 할 수 parameter
내부 run()
. 나는 여분의 일을 할 필요가 없었습니다 p = parameter
.
final
더 이상 그렇게 중요하지 않습니다. 변수가 효과적으로 최종적 이면 충분합니다 (유해하지는 않지만)
Runnable 또는 Thread 클래스의 생성자를 통해
class MyThread extends Thread {
private String to;
public MyThread(String to) {
this.to = to;
}
@Override
public void run() {
System.out.println("hello " + to);
}
}
public static void main(String[] args) {
new MyThread("world!").start();
}
@Override
에게 필요한가?
@Override
Thread 클래스의 추상 메서드를 재정의하고 있다고 명시 적으로 설명합니다.
이 답변은 매우 늦었지만 누군가 유용 할 것입니다. Runnable
명명 된 클래스를 선언하지 않고 매개 변수를 전달하는 방법에 관한 것입니다 (라이너에게 편리함).
String someValue = "Just a demo, really...";
new Thread(new Runnable() {
private String myParam;
public Runnable init(String myParam) {
this.myParam = myParam;
return this;
}
@Override
public void run() {
System.out.println("This is called from another thread.");
System.out.println(this.myParam);
}
}.init(someValue)).start();
물론 start
보다 편리하거나 적절한 순간에 실행을 연기 할 수 있습니다 . 그리고 init
메소드 의 서명이 무엇인지 (따라서 더 많은 인수 및 / 또는 다른 인수가 필요할 수 있음) 물론 이름조차도 당신에게 달려 있지만 기본적으로 아이디어를 얻습니다.
실제로 이니셜 라이저 블록을 사용하여 익명 클래스에 매개 변수를 전달하는 다른 방법도 있습니다. 이걸 고려하세요:
String someValue = "Another demo, no serious thing...";
int anotherValue = 42;
new Thread(new Runnable() {
private String myParam;
private int myOtherParam;
{
this.myParam = someValue;
this.myOtherParam = anotherValue;
}
@Override
public void run() {
System.out.println("This comes from another thread.");
System.out.println(this.myParam + ", " + this.myOtherParam);
}
}).start();
모든 것은 초기화 블록 내부에서 발생합니다.
this.myParam
그때 정말로 필요합니까? 개인 변수를 삭제하고 외부 범위에서 변수를 참조 할 수 없습니까? 물론 스레드를 시작한 후 변수가 열려 열려있는 것과 같은 의미가 있음을 이해합니다.
스레드를 만들 때의 인스턴스가 필요합니다 Runnable
. 매개 변수를 전달하는 가장 쉬운 방법은 생성자에 인수로 전달하는 것입니다.
public class MyRunnable implements Runnable {
private volatile String myParam;
public MyRunnable(String myParam){
this.myParam = myParam;
...
}
public void run(){
// do something with myParam here
...
}
}
MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();
스레드가 실행되는 동안 매개 변수를 변경하려면 실행 가능한 클래스에 setter 메서드를 추가하면됩니다.
public void setMyParam(String value){
this.myParam = value;
}
이 작업을 마치면 다음과 같이 호출하여 매개 변수 값을 변경할 수 있습니다.
myRunnable.setMyParam("Goodbye World");
물론 매개 변수가 변경 될 때 작업을 트리거하려면 잠금을 사용해야하므로 상황이 훨씬 복잡해집니다.
당신이 중 하나를 확장 할 수 있습니다 또는를 원하는대로 매개 변수를 제공합니다. 문서 에는 간단한 예제가 있습니다 . 여기에 포트하겠습니다 :Thread
class
Runnable
class
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
Runnable을 구현하는 클래스를 작성하고 적절하게 정의 된 생성자에 필요한 것을 전달하거나 적절한 매개 변수를 사용하여 super ()를 호출하는 적절하게 정의 된 생성자로 Thread를 확장하는 클래스를 작성하십시오.
Java 8부터 람다를 사용하여 효과적으로 최종적인 매개 변수를 캡처 할 수 있습니다 . 예를 들면 다음과 같습니다.
final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
// Do whatever you want here: param1 and param2 are in-scope!
System.out.println(param1);
System.out.println(param2);
}).start();
자바 8에서는 사용할 수 lambda
와 표현 동시성 API &을 ExecutorService
직접 스레드 작업을위한 높은 수준의 대체 :
newCachedThreadPool()
필요에 따라 새 스레드를 작성하는 스레드 풀을 작성하지만 사용 가능한 경우 이전에 구성된 스레드를 재사용합니다. 이러한 풀은 일반적으로 많은 단기 비동기 작업을 실행하는 프로그램의 성능을 향상시킵니다.
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
executors
javadocs 도 참조하십시오 .
start () 및 run () 메소드를 통한 매개 변수 전달 :
// Tester
public static void main(String... args) throws Exception {
ThreadType2 t = new ThreadType2(new RunnableType2(){
public void run(Object object) {
System.out.println("Parameter="+object);
}});
t.start("the parameter");
}
// New class 1 of 2
public class ThreadType2 {
final private Thread thread;
private Object objectIn = null;
ThreadType2(final RunnableType2 runnableType2) {
thread = new Thread(new Runnable() {
public void run() {
runnableType2.run(objectIn);
}});
}
public void start(final Object object) {
this.objectIn = object;
thread.start();
}
// If you want to do things like setDaemon(true);
public Thread getThread() {
return thread;
}
}
// New class 2 of 2
public interface RunnableType2 {
public void run(Object object);
}
아니요 run()
메소드에 매개 변수를 전달할 수 없습니다 . 서명은 (매개 변수가 없음)을 알려줍니다. 아마도 가장 쉬운 방법은 생성자에서 매개 변수를 가져 와서 최종 변수에 저장하는 특수 목적 객체를 사용하는 것입니다.
public class WorkingTask implements Runnable
{
private final Object toWorkWith;
public WorkingTask(Object workOnMe)
{
toWorkWith = workOnMe;
}
public void run()
{
//do work
}
}
//...
Thread t = new Thread(new WorkingTask(theData));
t.start();
일단 당신이-당신은 'WorkingTask'에 전달하는 객체의 데이터 무결성에주의해야합니다. 데이터는 이제 두 개의 다른 스레드에 존재하므로 스레드 안전인지 확인해야합니다.
하나의 추가 옵션; 이 방법을 사용하면 비동기 함수 호출과 같은 Runnable 항목을 사용할 수 있습니다. 작업이 결과를 반환 할 필요가없는 경우, 예를 들어 "결과"를 어떻게 다시 전달할 것인지에 대해 걱정할 필요가없는 일부 작업 만 수행합니다.
이 패턴을 사용하면 일종의 내부 상태가 필요한 항목을 재사용 할 수 있습니다. 생성자에서 매개 변수를 전달하지 않으면 매개 변수에 대한 프로그램 액세스를 중재하기 위해주의를 기울여야합니다. 사용 사례에 다른 발신자 등이 포함 된 경우 추가 확인이 필요할 수 있습니다.
public class MyRunnable implements Runnable
{
private final Boolean PARAMETER_LOCK = false;
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void setParameter( final X newParameter ){
boolean done = false;
synchronize( PARAMETER_LOCK )
{
if( null == parameter )
{
parameter = newParameter;
done = true;
}
}
if( ! done )
{
throw new RuntimeException("MyRunnable - Parameter not cleared." );
}
}
public void clearParameter(){
synchronize( PARAMETER_LOCK )
{
parameter = null;
}
}
public void run() {
X localParameter;
synchronize( PARAMETER_LOCK )
{
localParameter = parameter;
}
if( null != localParameter )
{
clearParameter(); //-- could clear now, or later, or not at all ...
doSomeStuff( localParameter );
}
}
}
스레드 t = 새 스레드 (new MyRunnable (parameter)); t.start ();
처리 결과가 필요한 경우 하위 작업이 완료 될 때 MyRunnable 완료를 조정해야합니다. 전화를 다시 받거나 Thread 't'등을 기다릴 수 있습니다.
콜백을 위해 일반적 Runnable
으로 입력 매개 변수를 사용하여 제네릭 을 구현합니다 .
public interface Runnable<TResult> {
void run(TResult result);
}
사용법은 간단합니다.
myManager.doCallbackOperation(new Runnable<MyResult>() {
@Override
public void run(MyResult result) {
// do something with the result
}
});
관리자 :
public void doCallbackOperation(Runnable<MyResult> runnable) {
new AsyncTask<Void, Void, MyResult>() {
@Override
protected MyResult doInBackground(Void... params) {
// do background operation
return new MyResult(); // return resulting object
}
@Override
protected void onPostExecute(MyResult result) {
// execute runnable passing the result when operation has finished
runnable.run(result);
}
}.execute();
}
클래스에서 지역 변수를 만들 extends Thread
거나 implements Runnable
.
public class Extractor extends Thread {
public String webpage = "";
public Extractor(String w){
webpage = w;
}
public void setWebpage(String l){
webpage = l;
}
@Override
public void run() {// l is link
System.out.println(webpage);
}
public String toString(){
return "Page: "+webpage;
}}
이런 식으로 변수를 실행할 때 변수를 전달할 수 있습니다.
Extractor e = new Extractor("www.google.com");
e.start();
출력 :
"www.google.com"