Es gibt zwei Möglichkeiten, einen Thread zu erstellen: Eine besteht darin, Thread direkt zu erben, und die andere darin, die Runnable-Schnittstelle zu implementieren
Unterschied: Die Schnittstelle kann Mehrfachvererbung implementieren
Der Fehler ist: nach der Ausführung der Aufgabe Die Ausführungsergebnisse können danach nicht abgerufen werden
Callable and Runnable
java.lang.Runnable
[code]public interface Runnable { public abstract void run(); }
Da der Rückgabewert des Laufs( )-Methode vom Typ „void“ ist, wird die Aufgabe nicht ausgeführt, nachdem keine Ergebnisse zurückgegeben werden können.
java.util.concurren
[code]public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }
Generische Schnittstelle, der von der Funktion call() zurückgegebene Typ ist der übergebene V-Typ
Im Allgemeinen wird er in verwendet Verbindung mit ExecutorService Verwendet werden mehrere überladene Versionen der Submit-Methode in der ExecutorService-Schnittstelle deklariert
[code]<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);
Future
Future dient dazu, die Ausführungsergebnisse bestimmter ausführbarer oder aufrufbarer Aufgaben abzubrechen und abzufragen. Abschließen, Ergebnisse erhalten. Bei Bedarf können Sie das Ausführungsergebnis über die get-Methode abrufen. Diese Methode blockiert, bis die Aufgabe das Ergebnis zurückgibt. Die Abbruchmethode wird verwendet, um die Aufgabe abzubrechen , gibt es „true“ zurück. Wenn der Aufgabenabbruch fehlschlägt, wird „false“ zurückgegeben. Der Parameter mayInterruptIfRunning gibt an, ob ausgeführte, aber noch nicht abgeschlossene Aufgaben abgebrochen werden dürfen. Wenn er auf true gesetzt ist, bedeutet dies, dass laufende Aufgaben abgebrochen werden können. Wenn die Aufgabe abgeschlossen wurde, unabhängig davon, ob mayInterruptIfRunning wahr oder falsch ist, gibt diese Methode definitiv false zurück. Das heißt, wenn die abgeschlossene Aufgabe abgebrochen wird, gibt sie false zurück, wenn die Aufgabe ausgeführt wird, wenn mayInterruptIfRunning auf true gesetzt ist. Es wird „true“ zurückgegeben. Wenn „mayInterruptIfRunning“ auf „false“ gesetzt ist, wird „false“ zurückgegeben. Wenn die Aufgabe nicht ausgeführt wurde, wird „mayInterruptIfRunning“ auf jeden Fall „true“ zurückgegeben.
[code]public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
Die Methode isDone gibt an, ob die Aufgabe abgeschlossen ist.
Die Methode get() wird verwendet, um das Ausführungsergebnis zu erhalten wartet, bis die Aufgabe abgeschlossen ist, bevor sie zurückgegeben wird.
get(long timeout, TimeUnit unit) wird verwendet, um das Ausführungsergebnis zu erhalten. Wenn das Ergebnis nicht innerhalb der angegebenen Zeit erhalten wird, wird null zurückgegeben.
Das heißt, Future bietet drei Funktionen:
1) Bestimmen, ob die Aufgabe abgeschlossen ist
2) Kann die Aufgabe unterbrechen; > 3) Kann Ergebnisse der Aufgabenausführung abrufen.
Da Future nur eine Schnittstelle ist, kann es nicht direkt zum Erstellen von Objekten verwendet werden. Daher gibt es die folgende FutureTask.
FutureTask
Tatsächlich ist FutureTask die einzige Implementierungsklasse der Future-Schnittstelle.
[code]public class FutureTask<V> implements RunnableFuture<V>
[code]public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
[code]public FutureTask(Callable<V> callable) { } public FutureTask(Runnable runnable, V result) { }
[code]public class Test { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> result = executor.submit(task); executor.shutdown(); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主线程在执行任务"); try { System.out.println("task运行结果"+result.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任务执行完毕"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子线程在进行计算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
[code]public class Test { public static void main(String[] args) { //第一种方式 ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); executor.submit(futureTask); executor.shutdown(); //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread /*Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); Thread thread = new Thread(futureTask); thread.start();*/ try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主线程在执行任务"); try { System.out.println("task运行结果"+futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任务执行完毕"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子线程在进行计算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }