IT이야기

Java 스레드에 매개 변수를 전달하는 방법

cyworld 2022. 5. 16. 21:06
반응형

Java 스레드에 매개 변수를 전달하는 방법

내가 어떻게 매개 변수를 실로 전달할 수 있는지 누가 나에게 제안해 줄 수 있니?

또한, 익명 수업에는 어떤 효과가 있을까?

생성자의 매개 변수를 실행 가능한 개체로 전달해야 하는 경우:

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();

익명 클래스의 경우:

질문 편집에 대한 응답은 익명 클래스에 대해 어떻게 작동하는지 입니다.

   final X parameter = ...; // the final is important
   Thread t = new Thread(new Runnable() {
       p = parameter;
       public void run() { 
         ...
       };
   t.start();

명명된 클래스:

스레드를 확장(또는 실행 가능을 구현)하는 클래스와 전달하려는 매개 변수를 가진 생성자가 있는 경우.그런 다음 새 스레드를 만들 때 인수를 전달한 다음 스레드를 시작해야 하는데, 다음과 같은 것이 있다.

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();

이 답은 기본적으로 이와 유사한 질문과 같다.스레드 개체로 매개 변수를 전달하는 방법

실행 가능 또는 스레드 클래스의 생성자를 통해

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();
}

이 대답은 매우 늦게 오지만, 누군가 유용하다고 여길지도 모른다.에 매개 변수를 전달하는 방법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;
        // instance initializer
        {
            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();

그래서 모든 일은 이니셜라이저 블록 안에서 일어난다.

때, 은 스스튜어드 의 가 필요하다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();

그런 다음 스레드가 실행되는 동안 매개 변수를 변경하려면 실행 가능한 클래스에 세터 메서드를 추가하십시오.

public void setMyParam(String value){
    this.myParam = value;
}

일단 이것을 가지고 있으면 다음과 같이 호출하여 파라미터의 값을 변경할 수 있다.

myRunnable.setMyParam("Goodbye World");

물론 파라미터가 변경되었을 때 액션을 트리거하려면 잠금장치를 사용해야 하기 때문에 사물이 상당히 복잡해진다.

몇 년 늦었다는 건 알지만 이 문제를 우연히 접하고 비정통적으로 접근했다.새로운 수업을 만들지 않고 하고 싶었기 때문에 이렇게 생각해 낸 것이다.

int x = 0;
new Thread((new Runnable() {
     int x;
     public void run() {
        // stuff with x and whatever else you want
     }
     public Runnable pass(int x) {
           this.x = x;
           return this;
     }
}).pass(x)).start();

다음 중 하나를 확장하십시오. class또는 그 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 구현을 직접 생성하십시오.이 클래스의 생성자에 있는 스레드에 매개 변수를 전달하십시오.

class MyThread implements Runnable{
   private int a;
   private String b;
   private double c;

   public MyThread(int a, String b, double c){
      this.a = a;
      this.b = b;
      this.c = c;
   }

   public void run(){
      doSomething(a, b, c);
   }
}

Runnable을 구현하는 클래스를 작성하고, 적절하게 정의된 생성자에서 필요한 모든 것을 통과시키거나, 적절한 매개 변수를 사용하여 super()를 호출하는 적절하게 정의된 생성자와 함께 스레드를 확장하는 클래스를 쓰십시오.

Java 8에서 당신은 사용할 수 있다.lambdaConcurrency API &가 포함된 표현식ExecutorService스레드를 직접 사용하기 위한 보다 높은 수준의 대체:

newCachedThreadPool()필요에 따라 새 스레드를 생성하지만 이전에 생성한 스레드가 있을 때 재사용하는 스레드 풀 생성.이러한 풀은 일반적으로 단명 비동기 작업을 많이 실행하는 프로그램의 성능을 향상시킬 것이다.

    private static final ExecutorService executor = Executors.newCachedThreadPool();

    executor.submit(() -> {
        myFunction(myParam1, myParam2);
    });

참고 항목executors 자바도크

자바 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();

시작() 및 실행() 방법을 통과하는 매개 변수:

// 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);
}

Runnable에서 클래스를 추출할 수 있으며, 시공 중에(예:) 매개 변수를 전달하십시오.

그런 다음 Thread.start(Runnable r)를 사용하여 실행하십시오;

스레드가 실행되는 동안, 호출 스레드에서 파생된 객체에 대한 참조를 잡고 적절한 세터 메서드를 호출하십시오(해당될 경우 동기화).

변수를 런너블에 전달하는 간단한 방법이 있다.코드:

public void Function(final type variable) {
    Runnable runnable = new Runnable() {
        public void run() {
            //Code adding here...
        }
    };
    new Thread(runnable).start();
}

에 매개 변수를 전달할 수 없음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'에 전달되는 개체의 데이터 무결성에 주의해야 한다.이제 데이터가 서로 다른 두 개의 스레드에 존재하므로 스레드가 안전한지 확인해야 한다.

한 가지 추가 옵션: 이 접근 방식을 통해 비동기 함수 호출과 같이 실행 가능한 항목을 사용할 수 있다.만약 여러분의 과제가 결과를 반환할 필요가 없다면, 예를 들어, 그것은 여러분이 어떻게 "발견"을 반환하는지에 대해 걱정할 필요가 없는 몇몇 행동을 할 뿐이다.

이 패턴은 당신이 어떤 내부 상태를 필요로 하는 항목을 재사용할 수 있게 해준다.매개 변수를 전달하지 않을 경우 매개 변수에 대한 프로그램 액세스를 중재하기 위해 생성자 관리에서 매개 변수를 전달해야 한다.사용 사례에 다른 발신자 등이 포함된 경우 더 많은 확인이 필요할 수 있다.

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 = 새 스레드(새 MyRunnable(매개 변수)), t.start();

처리 결과가 필요한 경우 하위 태스크가 완료될 때 MyRunnable의 완료도 조정해야 한다.전화를 돌려주거나 'T'등에서 그냥 기다릴 수도 있다.

특별히 Android용

콜백(callback)을 위해 나는 보통 나만의 일반을 구현한다.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"

먼저 나는 다른 답변들이 사실이라는 것을 지적하고 싶다.그러나, 생성자의 매개변수를 사용하는 것이 여러분 모두에게 가장 좋은 아이디어는 아닐 수 있다.

많은 시나리오에서 당신은 "익명 이너 클래스"를 사용하기를 원할 것이고, 그리고 오버라이드 할 것이다.run()방법, 모든 사용에 대한 특정 클래스를 정의하는 것은 고통스럽기 때문이다.(new MyRunnable(){...})

Runnable을 생성할 때 생성자에서 매개 변수를 전달하지 못할 수 있음예를 들어, 이 개체를 하나의 메서드에 전달하면 별도의 스레드에서 작업을 수행한 다음 실행 가능을 호출하여 해당 작업의 결과를 해당 메서드에 적용하십시오.

이 경우 다음과 같은 방법을 사용하여 다음을 수행하십시오.public MyRunnable withParameter(Object parameter)는 훨씬 더 유용한 선택으로 판명될지도 모른다.

나는 이것이 그 문제에 대한 최선의 해결책이라고 주장하지는 않지만, 그것은 그 일을 끝낼 것이다.

참조URL: https://stackoverflow.com/questions/877096/how-can-i-pass-a-parameter-to-a-java-thread

반응형