Java并发编程—说说Runnable与Callable
原文作者:每天一點
原文地址:說說Runnable與Callable
首先,我們先看看使用Callable創建線程與使用Runable的區別:
import java.util.concurrent.Callable;//實現Runable class MyThread implements Runnable {@Overridepublic void run() {} }//實現Callable class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {return null;} }首先,實現Callable而重寫的方法具有返回值,并且擁有泛型,這提高了線程的細粒度。
實現Runable接口創建線程方式:
//實現Runable創建線程的方式 MyThread myThread = new MyThread(); Thread thread = new Thread(myThread);實現Callable接口創建線程方式
查閱API我們可以發現,在Thread的構造方法中并沒有使用Callable作為參數的構造器。解決辦法:我們先查看Runable接口,
可以發現有一個FutureTask的實現類,點進這個實現類,我們可以發現在這個類的構造方法中就可以傳Callable對象
所以我們可以借助FutureTask這個類,具體創建代碼如下:
//實現Callable創建線程的方式 FutureTask futureTask = new FutureTask(new MyThread1()); Thread thread1 = new Thread(futureTask);這里有個細節:如果我們在使線程睡眠5秒鐘,然后使用futureTask.get()方法,會發現結果會等5秒才出現,說明get()方法是有阻塞效果
//實現Callable class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("進入方法中");Thread.sleep(5000);return 1000;} }public class Test {public static void main(String[] args) {//實現Callable創建線程的方式FutureTask futureTask = new FutureTask(new MyThread1());new Thread(futureTask, "AAA").start();try {System.out.println(futureTask.get());System.out.println("main");} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}} }并且只執行了一次,因為一個futureTask,不管幾個線程調用,調用的都是同一個futureTask對象
Callable接口:
public interface Callable<V> {V call() throws Exception; }Runnable接口:
public interface Runnable {public abstract void run(); }相同點:
不同點:
注意點:
- Callable接口支持返回執行結果,此時需要調用FutureTask.get()方法實現,此方法會阻塞主線程直到獲取‘將來’結果;當不調用此方法時,主線程不會阻塞!
寫此篇的原因是一次面試中問到Callable與Runnable的區別,當時用的多的是Runnable,而Callable使用很少!比較了兩者后(網上查了不少),發現Callable在很多特殊的場景下還是很有用的!最后留點抄的代碼,加深對Callable的認識!
package com.inte.fork; import java.util.*; import java.util.concurrent.*; import static java.util.Arrays.asList;public class Sums {static class Sum implements Callable<Long> {private final long from;private final long to;Sum(long from, long to) {this.from = from;this.to = to;}@Overridepublic Long call() {long acc = 0;for (long i = from; i <= to; i++) {acc = acc + i;}System.out.println(Thread.currentThread().getName() + " : " + acc);return acc;}}public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newFixedThreadPool(3);List<Future<Long>> results = executor.invokeAll(asList(new Sum(0, 10), new Sum(0, 1_000), new Sum(0, 1_000_000)));executor.shutdown();for (Future<Long> result : results) {System.out.println(result.get());}} }總結
以上是生活随笔為你收集整理的Java并发编程—说说Runnable与Callable的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java集合—List如何一边遍历,一边
- 下一篇: Java并发编程—notify和noti