1.示例代码: Runnable + ThreadPoolExecutor


首先创建一个 Runnable 接口的实现类(当然也可以是 Callable 接口,我们上面也说了两者的区


别。)


MyRunnable.java




import java.util.Date;

public class MyRunnable implements Runnable {
    private String command;
    public MyRunnable (String s){
        this.command = s;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " Start. Time = " + new Date());
        processCommand();
        System.out.println(Thread.currentThread().getName() + " End. Time = " + new Date());
    }

    private void processCommand() {

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return this.command;
    }
}



编写测试程序,我们这里以阿里巴巴推荐的使用 ThreadPoolExecutor 构造函数自定义参数的方式来



创建线程池。



ThreadPoolExecutorDemo.java




public class CallableDemo {
    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;

    public static void main(String[] args) {
        //使用阿里巴巴推荐的创建线程池的方式
        // 通过ThreadPoolExecutor构造函数自定义参数创建
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 10; i++) {
            //创建WorkerThread对象(WorkerThread类实现了Runnable 接口)
            Runnable worker = new MyRunnable("" + i);
            //执行Runnable 
            executor.execute(worker);
        }
        //终止线程池 
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }
}



可以看到我们上面的代码指定了:



1. corePoolSize : 核心线程数为 5 。



2. maximumPoolSize :最大线程数 10



3. keepAliveTime : 等待时间为 1L 。



4. unit : 等待时间的单位为 TimeUnit.SECONDS 。



5. workQueue :任务队列为 ArrayBlockingQueue ,并且容量为 100;



6. handler : 饱和策略为 CallerRunsPolicy 。





线程池原理图:




线程池复用demo 线程池使用demo_线程池复用demo


2.Runnable vs Callable


Runnable 自 Java 1.0 以来一直存在,但 Callable 仅在 Java 1.5 中引入 , 目的就是为了来处理


Runnable 不支持的用例。 Runnable 接口 不会返回结果或抛出检查异常,但是 Callable 接口 可以。


所以,如果任务不需要返回结果或抛出异常推荐使用 Runnable 接口 ,这样代码看起来会更加简洁。


工具类 Executors 可以实现 Runnable 对象和 Callable 对象之间的相互转换。


( Executors.callable ( Runnable task )或 Executors.callable ( Runnable task , Object


resule ) )


 


execute() vs submit()


execute() 方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;


submit() 方法用于提交需要返回值的任务。线程池会返回一个 Future 类型的对象,通过这个


Future 对象可以判断任务是否执行成功 ,并且可以通过 Future 的 get() 方法来获取返回值,


get() 方法会阻塞当前线程直到任务完成,而使用 get ( long timeout , TimeUnit unit ) 方法


则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。


shutdown() VS shutdownNow()


shutdown() : 关闭线程池,线程池的状态变为 SHUTDOWN 。线程池不再接受新任务了,但是队


列里的任务得执行完毕。


shutdownNow() : 关闭线程池,线程的状态变为 STOP 。线程池会终止当前正在运行的任务,并


停止处理排队的任务并返回正在等待执行的 List 。


i sTerminated() VS isShutdown()


isShutDown 当调用 shutdown() 方法后返回为 true 。


isTerminated 当调用 shutdown() 方法后,并且所有提交的任务完成后返回为 true




4.Callable + ThreadPoolExecutor 示例代码


import java.util.concurrent.Callable;

public class MyCallable implements Callable {
    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return Thread.currentThread().getName();
    }
}
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorDemo {

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 8;
    private static final int QUEUE_CAPACITY = 10;
    private static final Long KEEP_ALIVE_TIME = 1L;

    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 40; i++) {
            Runnable worker = new MyRunnable(">>" + i);
            threadPoolExecutor.execute(worker);
            System.out.println("worker>>" + i);
        }
        //终止线程
        threadPoolExecutor.shutdown();
        while (!threadPoolExecutor.isTerminated()){

        }
        System.out.println("Finished All Threads");
    }

}