Poate sugera cineva si mie cum pot trece de la un parametru la un fir?
De asemenea, cum funcționează pentru anonim clase?
Aveți nevoie pentru a trece parametru în constructor la obiect Runnable:
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
și invoca astfel:
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
Ca răspuns la întrebarea editează aici este modul în care funcționează pentru Anonim clase
final X parameter = ...; // the final is important
Thread t = new Thread(new Runnable() {
p = parameter;
public void run() {
...
};
t.start();
Ai o clasa care extinde Thread (sau implementeaza Runnable) și un constructor cu parametrii te'd dori să treacă. Apoi, atunci când vă creați noul fir, trebuie să treacă în argumente, și apoi începe fir, ceva de genul asta:
Thread t = new MyThread(args...);
t.start();
Runnable este o soluție mult mai bună decât Firul BTW. Așa că m-am'd prefera:
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();
Acest răspuns este în esență același ca această întrebare similară: Cum pentru a trece parametrii de la un Fir de obiect
prin constructor de o Runnable sau clasa Fir
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();
}
Acest răspuns vine foarte târziu, dar poate cineva va găsi că este util. Este vorba despre modul de a transmite un parametru(s) a o `Runnable fără declarând chiar și pe nume de clasă (la îndemână pentru inliners):
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();
Desigur, puteți amâna executarea de "start" pentru unii mai convenabil sau momentul potrivit. Și este de până la tine ceea ce va fi semnătura de init
metoda (deci este posibil să dureze mai mult și/sau argumente diferite) și, desigur, chiar numele său, dar practic ai o idee.
În fapt, nu există, de asemenea, un alt mod de a trece de la un parametru la un anonim din clasa, cu utilizarea de inițializare blocuri. Luați în considerare acest lucru:
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();
Deci, toate se întâmplă în interiorul de inițializare bloc.
Atunci când creați un fir, aveți nevoie de un exemplu de Runnable
. Cel mai simplu mod de a trece de la un parametru ar fi să-l treacă în ca argument pentru constructor:
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();
Apoi, dacă doriți să modificați parametrul timp ce firul se execută, puteți adăuga pur și simplu un setter metodă de a-ți runnable clasa:
public void setMyParam(String value){
this.myParam = value;
}
Odată ce aveți acest lucru, puteți schimba valoarea parametrului de apel de genul asta:
myRunnable.setMyParam("Goodbye World");
Desigur, dacă doriți pentru a declanșa o acțiune atunci când parametrul este schimbat, va trebui să utilizați încuietorile, ceea ce face lucrurile mult mai complex.
Pentru a crea un fir în mod normal crea propria dvs. punerea în aplicare a Runnable. Trece parametrii pentru firul în constructorul clasei.
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);
}
}
Puteți fie să prelungească Subiect
"clasa" sau Runnable
"clasa" și să ofere parametri, după cum doriți. Există exemple simple în documente. Am'll port-le aici:
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();
Fie scrie o clasa care implementeaza Runnable, și să treacă tot ce ai nevoie într-un mod adecvat definite de constructor, sau scrie o clasa care extinde Fir cu un corespunzător definit de constructor, care solicită super() cu parametrii corespunzători.
Ca de Java 8, puteți utiliza un lambda pentru a captura parametri care sunt mod eficient final. De exemplu:
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();
Parametru trece prin start() și() metode:
// 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);
}
Puteți obține o clasă de Runnable, și în timpul construcției (să zicem) trece parametru.
Apoi lansați-l folosind Fir.start(Runnable r);
Daca te referi la timp firul se execută, apoi pur și simplu țineți o referință la obiect derivat în firul de asteptare, și de apel adecvate metode setter (sincronizarea acolo unde este cazul)
În Java 8, puteți folosi "lambda" expresii cu Concurenta API & ExecutorService
ca un nivel mai ridicat de înlocuire pentru lucrul cu fire direct:
`newCachedThreadPool () Creează un thread pool care creează noi fire după cum este necesar, dar va reutiliza construite anterior fire atunci când acestea sunt disponibil. Aceste bazine de obicei, va îmbunătăți performanța de programe care executa multe de scurtă durată sarcini asincrone.
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
A se vedea, de asemenea, `executorilor javadocs.
Știu că m-am'm câțiva ani mai târziu, dar am dat peste această problemă și a luat-o abordare neortodoxă. Am vrut să fac, fără a face o nouă clasă, astfel încât aceasta este ceea ce am venit cu:
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();
Nu, nu se poate't trece parametrii la `run () metodă. Semnătura spune că (nu are parametri). Probabil cel mai simplu mod de a face acest lucru ar fi de a utiliza un scop-construit obiect care are un parametru în constructor și o stochează într-un final variabilă:
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();
Odată ce ați face asta, trebuie să ai grijă de integritatea datelor obiectului, va trece în 'WorkingTask'. Datele vor acum există în două fire diferite, deci trebuie să vă asigurați că acesta este Thread-Safe.
Pentru scopuri de apel invers de obicei pună în aplicare propriul meu generic `Runnable cu parametru de intrare(s):
public interface Runnable<TResult> {
void run(TResult result);
}
Utilizare este simplu:
myManager.doCallbackOperation(new Runnable<MyResult>() {
@Override
public void run(MyResult result) {
// do something with the result
}
});
În manager:
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();
}
O opțiune suplimentară; această abordare vă permite să utilizați Runnable element ca un asincrone apel de funcție. Daca sarcina ta nu are nevoie să se întoarcă un rezultat, de exemplu, nu doar îndeplinește o acțiune nu't nevoie să vă faceți griji despre cum vei ajunge acolo un "rezultat".
Acest model vă permite să reutilizați un articol, în cazul în care ai nevoie de un fel de stat interne. Când nu trece parametru(s) în constructorul este nevoie de grijă să medieze programe de acces la parametrii. Poate ai nevoie de mai multe controale dacă ți caz de utilizare implică diferite suna, etc.
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 );
}
}
}
Thread t = new Thread(new MyRunnable(parametru)); t.start();
Dacă aveți nevoie de un rezultat de prelucrare, de asemenea, va trebui să-și coordoneze finalizarea MyRunnable atunci când sub-sarcina inainteaza. Ai putea trece un apel înapoi sau doar stai pe Thread 't', etc.
Creați o variabilă locală în clasa care extinde Thread " sau " implementeaza 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;
}}
În acest fel, puteți trece o variabilă atunci când îl rulați.
Extractor e = new Extractor("www.google.com");
e.start();
Ieșire:
"www.google.com"