实现多线程在java中有三种方法,前两种比较常用。
继承Thread
1)继承Thread类,重写run方法
class MyThread extends Thread {
@Override
public void run(){
}
}
实现Runnable
2)实现Runnable接口
1.重写run方法,实例化后,再创建一个Thread的对象,将其传入Thread(object)方法中
2.创建一个Thread对象,使用匿名内部类实现Runnable接口。
Runnable接口中只声明了一个方法,返回类型为void。
public interface Runnable {
public abstract void run();
}
class MyThread implements Runnable {
@Override
public void run(){
System.out.println("runnable");
}
}
class Main {
public static void main(String[] args) {
MyThread th = new MyThread();
Thread run = new Thread(th);
Thread run2 = new Thread(new Runnable(){
public void run(){
System.out.println("inner runnable");
}
});
run.start();
run2.start();
}
}
实现Callable
3)实现Callable()接口,重写Call方法。
前两种创建线程的方式都包含一个缺陷,在执行完任务后无法获得执行结果。如果要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果。
Callable接口位于java.util.concurrent下,只包含一个方法。
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;
}
Callable一般配合ExecutorService接口中的submit方法来使用。
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
Future
java.util.concurrent
Future用于对具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。可以通过get()获取其执行结果,这个方法或阻塞知道获得任务返回的结果。
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;
}
cancel用来取消任务,若取消成功则返回true,取消失败则返回false。mayInterruptIfRunning用于表示是否取消(中断)正在执行却没有完成的任务,true表示可以取消。任务未开始执行和任务执行完成时,无论其值为true或false,都返回false,取消失败。若果任务正在执行,其值为true,则返回true,其值为false,则返回fasle。
isCancelled()用来查看任务是否被取消成功,取消成功返回true否则false。
isDone()用来判断任务是否执行完。
get()用来获取执行结果。
get(timeout, unit)用来在执行时间内获取结果,超时返回null。
由此可见,Future接口提供了三种功能:
1.判断任务是否完成。
2.设定是否中断任务。
3.可以获取任务的执行结果。
FutureTask
FutureTask是RunnableFuture接口一种实现:
public class FutureTask<V> implements RunnableFuture<V>
RunnableFuture接口继承了Runnable和Future接口,FutureTask实现了Runnable接口,它可以作为Runnable接口的实现被线程执行,又可以作为Future得到Callable的返回值。
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
FutureTask有两个构造器方法,分别可以使用Callable和Runnable的实现。
public FutureTask(Callable<V> callable) {
}
public FutureTask(Runnable runnable, V result) {
}
使用方法
1)Callable+Future
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
Future<String> result = executor.submit(task);
executor.shutdown();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("main process is running");
try {
System.out.println("result:"+result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("all tasks finished");
}
}
class Task implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("sub process is running");
Thread.sleep(3000);
return "String result from call";
}
}
2)Callable+FutureTask
FutureTask提供了使用Callable和Runnable两种实现。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
public static void main(String[] args) {
//1.Callable+FutureTask
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
FutureTask<String> ft = new FutureTask<String>(task);
executor.submit(task);
executor.shutdown();
//2.Callable+FutureTask+Thread
Task task = new Task();
FutureTask<String> ft = new FutureTask<String>(task);
Thread th = new Thread(ft);
th.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("main process is running");
try {
System.out.println("result:"+ft.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("all tasks finished");
}
}
class Task implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("sub process is running");
Thread.sleep(3000);
return "String result from call";
}
}
Callable接口与Runnable接口类似,区别如下:
| Callable | Runnable | |
|---|---|---|
| 返回值 | 提供 | 不提供 |
| 抛出异常 | call()可以 | run()不可以 |
| 异步计算结果 | 检查计算是否完成。 Future对象的get方法,阻塞线程 | 无 |