多线程
<h1>多线程</h1>
<h2>1 Runnable、Callable和Future</h2>
<h3>1.1 Runnable和Callable</h3>
<p>Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。</p>
<ul>
<li>Runnable需要重写run()方法,Callable需要重写call()方法;</li>
<li>Runnable任务执行后没有返回值,Callable执行任务后有返回值;</li>
<li>run()方法不可以抛出异常,call()方法可以抛出异常;</li>
</ul>
<h3>1.2 Future</h3>
<p>Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
Future接口:</p>
<pre><code class="language-java">public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);//取消任务
boolean isCancelled();//是否已经取消任务
boolean isDone();//是否已经完成任务
V get() throws InterruptedException, ExecutionException;//获取结果,阻塞
V get(long timeout, TimeUnit unit)//获取结果,设置超时,超时返回null
throws InterruptedException, ExecutionException, TimeoutException;
}</code></pre>
<h3>1.3 FutureTask</h3>
<p>FutureTask的实现:</p>
<pre><code>public class FutureTask<V> implements RunnableFuture<V></code></pre>
<p>RunnableFuture的实现:</p>
<pre><code class="language-java">public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}</code></pre>
<p>可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。</p>
<p>FutureTask提供了2个构造器:</p>
<pre><code>public FutureTask(Callable<V> callable) {}
public FutureTask(Runnable runnable, V result) {}</code></pre>
<h3>1.4 demo</h3>
<ul>
<li>
<p>使用Callable+Future获取执行结果</p>
<pre><code class="language-java">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></pre>
</li>
<li>
<p>使用Callable+FutureTask获取执行结果</p>
<pre><code class="language-java">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;
}
}</code></pre>
</li>
</ul>