1.示例代码: Runnable + ThreadPoolExecutor
首先创建一个 Runnable 接口的实现类(当然也可以是 Callable 接口,我们上面也说了两者的区 别。) MyRunnable.javaimport 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
。
线程池原理图:
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 ) )3. 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");
}
}



