Executor
基于生产者-消费者模式,用于异步处理线程(提交、执行等)。
Executor里有一个excute(Runnable)方法,用于执行线程。
ExecutorService
ExecutorService继承于Executor,也是一个接口,它主要有以下方法:
execute(Runnable)//执行Runnable
submit(Runnable)//提交Runnable
submit(Callable)//提交Callable,会返回一个Future对象,可以后去线程执行的返回值。
invokeAny(...)//参数是Callable的集合,不会返回一个Future对象,而是返回集合中某个线程执行后的值,具体是哪一个线程返回的是不确定的。但是返回值了说明所有线程都执行成功了。
invokeAll(...)//参数是Callable的集合,会返回一个List<Future>,存储每个线程的返回值。
execute
ExecutorService executorService = Executors.newFixedThreadPool(3);
创建了一个线程池,大小为3,也就是一次可以异步执行3个线程,
然后调用execute()来执行这些线程。
public class Test6 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(new Th6("th1"));
executorService.execute(new Th6("th2"));
executorService.execute(new Th6("th3"));
executorService.execute(new Th6("th4"));
executorService.execute(new Th6("th5"));
}
}
class Th6 implements Runnable{
private int a;
private String name ;
public Th6(String name){
this.name = name;
}
@Override
public void run() {
while (a<2){
System.out.println(name+" : "+(a++));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出结果如下:
th1 : 0
th2 : 0
th3 : 0
th1 : 1
th2 : 1
th3 : 1
th4 : 0
th5 : 0
th5 : 1
th4 : 1
可以看到一次只能执行3个线程,先执行了前3个线程,执行完后再执行后两个线程。
submit
对于submit(Runnable)和execute(Runnable)的效果是相似的,不在测试。
下面是传入参数为Callbale时的测试:
public class Test6 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
Future<String> future = executorService.submit(new ThC("th7"));
try {
System.out.println(future.get());//获取返回值
System.out.println(future.isCancelled());//任务是否取消
System.out.println(future.cancel(false));//取消任务(放在这里好像没意义)
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class ThC implements Callable<String>{
private String name ;
public ThC(String name){
this.name = name;
}
@Override
public String call() throws Exception {
System.out.println(name);
return "hello Callable";
}
}
输出如下:
th7
hello Callable
false
false
invokeAny
传入参数是Callable的集合,返回的是其中某个线程直线后的返回值,但是不确定是哪一个。
public class Test6 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
list.add(new ThC("Callable1"));
list.add(new ThC2("Callable2"));
try {
System.out.println(executorService.invokeAny(list));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class ThC implements Callable<String>{
private String name ;
public ThC(String name){
this.name = name;
}
@Override
public String call() throws Exception {
System.out.println(name);
return "hello Callable1";
}
}
class ThC2 implements Callable<String>{
private String name ;
public ThC2(String name){
this.name = name;
}
@Override
public String call() throws Exception {
System.out.println(name);
return "hello Callable2";
}
}
输出结果:
有时候是:
Callable1
Callable2
hello Callable1
有时候是:
这也说明了返回的值不确定是哪一个下线程的。
Callable1
Callable2
hello Callable2
invokeAll
public class Test6 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
List<Callable<String>> list = new ArrayList<>();
list.add(new ThC("Callable1"));
list.add(new ThC2("Callable2"));
try {
for (Future<String> future : executorService.invokeAll(list)){
System.out.println(future.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class ThC implements Callable<String>{
private String name ;
public ThC(String name){
this.name = name;
}
@Override
public String call() throws Exception {
Thread.sleep(1000);
System.out.println(name);
return "hello Callable1";
}
}
class ThC2 implements Callable<String>{
private String name ;
public ThC2(String name){
this.name = name;
}
@Override
public String call() throws Exception {
System.out.println(name);
return "hello Callable2";
}
}
输出结果:
Callable2
Callable1
hello Callable1
hello Callable2
上边代码中在ThC线程中加延时了1秒执行,目的是为了测试返回Future对象集合的顺序性,由输出顺序可以看到,返回的Future对象集合的顺序是原Callable集合中的顺序,也就是说Executor的invokeAll方法是在所有Callable集合线程执行完之后才返回的,并且保证了返回的顺序性。
线程池
Executors下有以下几种方式创建线程池: