Java5以前,编写并发程序就要创建Runnable对象,然后创建Thread对象,来执行这些Runnable对象,这样的方式不利于开发大量并发任务。
Java5开始提供了执行器框架机制,这种机制只需要创建Runnable对象即可,执行器会创建线程,负责Runnable对象的创建、实例化以及运行。并且执行器通过使用线程池提高了性能。线程池的应用,使得不会持续地创建和销毁线程而导致性能的下降。
下面是执行器创建的实例:
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class Server {
private ThreadPoolExecutor executor;
public Server(){
executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
}
public void execute(Task task){
System.out.println("Server: A new task has arrived");
executor.execute(task);
System.out.println("Server: Pool Size: "+executor.getPoolSize());
System.out.println("Server: Active Count: "+executor.getActiveCount());
System.out.println("Server: Completed Tasks: "+executor.getCompletedTaskCount());
}
public void endServer(){
executor.shutdown();
}
}
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class Task implements Runnable{
private Date initDate;
private String name;
public Task(String name){
initDate = new Date();
this.name = name;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+": Task "+name+" : Created on: "+initDate);
System.out.println(Thread.currentThread().getName()+": Task "+name+" : Started on: "+new Date());
try {
Long duration = (long)(Math.random()*10);
System.out.println(Thread.currentThread().getName()+": Task "+name+": Doing a task during "+duration+" seconds");
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+": Task "+name+": Finished on: "+new Date());
}
}
public class Main {
public static void main(String[] args){
Server server = new Server();
for(int i=0; i<100; i++){
Task task = new Task("Task "+i);
server.execute(task);
}
server.endServer();
}
}
执行器的创建相对于手动创建Thread对象来说,还是更加简洁的。
ThreadPoolExecutor类有四个不同的构造器,但是这些构造器使用起来比较复杂,需要传入很多参数。程序中就是使用Executors工厂类的newCachedThreadPool()方法创建了一个缓存线程池。
执行器需要显示地去结束,如果不结束,那么执行器将会持续执行下去,程序也不会结束。
newFixedThreadPool(int i)会创建一个固定大小的线程执行器。发送的任务超过最大值得任务时,执行器不会创建新的线程,剩下的任务将会阻塞知道执行器有空闲的线程可用。
newSingleThreadPool()创建一个只有单个线程的执行器,同一时间只能执行一个任务。Callable类似于Runnable接口,但又有很多的区别,需要实现call()方法,而且call方法可以返回任何对象。
Future对象,用来获取Callable对象产生的结果,并管理它们的状态。
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
public class FactorialCalculator implements Callable<Integer>{
private Integer number;
public FactorialCalculator(Integer number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int result = 1;
if((number == 0) || number == 1){
result = 1;
}else{
for(int i=2; i<=number; i++){
result*=i;
TimeUnit.MILLISECONDS.sleep(20);
}
}
System.out.println(Thread.currentThread().getName()+": "+result+"& initialNumber: "+number);
return result;
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(2);
List<Future<Integer>> resultList = new ArrayList<Future<Integer>>();
Random random = new Random();
for(int i=0; i<10; i++){
Integer number = random.nextInt(10);
FactorialCalculator calculator = new FactorialCalculator(number);
Future<Integer> result = executor.submit(calculator);
resultList.add(result);
}
do{
System.out.println("Main: Number of Completed Tasks:"+executor.getCompletedTaskCount());
for(int i=0; i<resultList.size(); i++){
Future<Integer> result = resultList.get(i);
System.out.println("Main: Task "+i+": "+result.isDone());
}
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while(executor.getCompletedTaskCount()<resultList.size());
System.out.println("Main: Results");
for(int i=0; i<resultList.size(); i++){
Future<Integer> result = resultList.get(i);
Integer number = null;
try {
number = result.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("Main: Task "+i+": "+number);
}
executor.shutdown();
}
}
invokeAny()接受一个任务列表,然后运行任务并返回第一个完成任务并且没有抛出异常的任务的执行结果。返回类型与call()方法的返回类型相同。
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class UserValidator {
private String name;
public UserValidator(String name){
this.name = name;
}
public boolean validate(String name,String password){
Random random = new Random();
long duration = (long)(Math.random()*10);
System.out.println("Validator "+this.name+": Validating a user during "+duration+" seconds");
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return random.nextBoolean();
}
public String getName(){
return name;
}
}
import java.util.concurrent.Callable;
public class TaskValidator implements Callable<String>{
private UserValidator validator;
private String user;
private String password;
public TaskValidator(UserValidator validator,String user,String password){
this.validator = validator;
this.user = user;
this.password = password;
}
@Override
public String call() throws Exception {
if(!validator.validate(user, password)){
System.out.println(validator.getName()+": The user has not been found");
throw new Exception("Error validating user");
}
System.out.println(validator.getName()+": The user has been found");
return null;
};
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args){
String username = "test";
String password = "test";
UserValidator ldapValidator = new UserValidator("LDAP");
UserValidator dbValidator = new UserValidator("DataBase");
TaskValidator ldapTask = new TaskValidator(ldapValidator, username, password);
TaskValidator dbTask = new TaskValidator(dbValidator, username, password);
List<TaskValidator> taskList = new ArrayList<TaskValidator>();
taskList.add(ldapTask);
taskList.add(dbTask);
ExecutorService executor = (ExecutorService)Executors.newCachedThreadPool();
String result;
try {
result = executor.invokeAny(taskList);
System.out.println("Main: Result: "+result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("Main: End of Execution");
}
}
invokeAll()等待所有任务的完成。
public class Result {
private String name;
private int value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
public class Task implements Callable<Result>{
private String name;
public Task(String name){
this.name = name;
}
@Override
public Result call(){
System.out.println(this.name+": Starting");
long duration = (long)(Math.random()*10);
System.out.println(this.name+": Waiting "+duration+" seconds for results.");
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
int value = 0;
for(int i=0; i<5; i++){
value+=(int)(Math.random()*100);
}
Result result = new Result();
result.setName(this.name);
result.setValue(value);
System.out.println(this.name+": Ends");
return result;
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args){
ExecutorService executor = (ExecutorService)Executors.newCachedThreadPool();
List<Task> taskList = new ArrayList<Task>();
for(int i=0; i<3; i++){
Task task = new Task("task "+i);
taskList.add(task);
}
List<Future<Result>> resultList = null;
try {
resultList = executor.invokeAll(taskList);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("Main: Printing the results");
for(int i=0; i<resultList.size(); i++){
Future<Result> future = resultList.get(i);
Result result = new Result();
System.out.println(result.getName()+": "+result.getValue());
}
}
}
newSchefuledThreadPool(int i)方法创建一个ScheduledThreadPoolExecutor执行器,通过schedule()方法延时执行任务,并需要传递一个整型参数,表示线程池中拥有的线程数。
import java.util.Date;
import java.util.concurrent.Callable;
public class Task implements Callable<String>{
private String name;
public Task(String name){
this.name = name;
}
@Override
public String call() throws Exception {
System.out.println(name+": Starting at : "+new Date());
return "Hello,world";
}
}
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);
System.out.println("Main: Starting at: "+new Date());
for(int i=0; i<5; i++){
Task task = new Task("Task "+i);
executor.schedule(task, i+1, TimeUnit.SECONDS);
}
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main: Ends at: "+new Date());
}
}