在線程池使用Callable和Runnable的區別以及如何關閉線程


一、區別總結:

  1. Callable定義的方法是call,而Runnable定義的方法是run。
  2. Callable的call方法可以有返回值,而Runnable的run方法不能有返回值,這是核心區別。
  3. Callable的call方法可拋出異常,而Runnable的run方法不能拋出異常。

二、返回值的區別

  他們的核心區別是Callable可以返回Feature的對象,這個對象可以了解線程的運行情況,設置可以關閉線程!

三、Runnable代碼事例

package com.qunar.synchro;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by qiu.li on 2015/9/21.
 * 這是一個繼承Runnable的例子
 */
public class TestRunnable implements Runnable {

    public static void main(String[] args) {

        ExecutorService runnableService = Executors.newFixedThreadPool(3);

        Runnable r1 = new TestRunnable();
        runnableService.submit(r1);
        runnableService.submit(new TestRunnable());
        runnableService.submit(new TestRunnable());
        runnableService.submit(new TestRunnable());
        runnableService.shutdown();
        
        System.out.println("go on");
        System.out.println("end");
    }

    @Override
    public void run() {
        for(int i=0;i<5; i++) {
            System.out.println(Thread.currentThread().getName() + ";random:" + (int) (Math.random() * 10 * 1000));
            try {
                Thread.sleep( (int) (Math.random() * 10 * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

他的輸出也比較簡單,

pool-1-thread-2;random:9491
go on
end
pool-1-thread-3;random:6983
pool-1-thread-1;random:718
pool-1-thread-2;random:4214.....

Process finished with exit code 0

四、Callable代碼

package com.qunar.synchro;

import com.sun.org.apache.xalan.internal.utils.FeatureManager;

import java.util.concurrent.*;

/**
 * Created by qiu.li on 2015/9/21.
 */
public class TestCallable implements Callable<Boolean> {

    int i;

    public static void main(String[] args) {

        ExecutorService runnableService = Executors.newFixedThreadPool(3);

        Future<Boolean> r1 =  runnableService.submit(new TestCallable(1));
        Future<Boolean> r2 =  runnableService.submit(new TestCallable(2));
        Future<Boolean> r3 =  runnableService.submit(new TestCallable(3));
        try {
            boolean b2 = r2.get(); //r2先跑
            boolean b3 = r3.get(); //r3先跑
            System.out.println(b2);
            System.out.println(b3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        r1.cancel(true);//r1是死循環,現在退出
        runnableService.shutdownNow();
    }

    public TestCallable(int i){
        this.i = i;
    }

    @Override
    public Boolean call() {
        try {
            switch (i){
                case 1:
                    while(true) {
                        System.out.println(Thread.currentThread().getName() + ";i:" + this.i); //第一個線程
                        Thread.sleep(200);
                    }
                default:
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName() + ";i:" + this.i); //其他線程
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return true;
    }
}

運行的結果:

pool-1-thread-1;i:1
pool-1-thread-1;i:1
pool-1-thread-1;i:1
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.qunar.synchro.TestCallable.call(TestCallable.java:46)
    at com.qunar.synchro.TestCallable.call(TestCallable.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
pool-1-thread-2;i:2
pool-1-thread-3;i:3
true
true

Process finished with exit code 0

大家可以看見拋出的異常,這是因為在線程1被阻塞的時候(比如被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞時),由於沒有占用CPU,是不能給自己的中斷狀態置位的,這就會產生一個InterruptedException異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM