Java线程池总结

Java线程池创建和使用

线程池就是一组线程实时处理休眠状态,等待唤醒执行。使用线程池有两个优点

  • 减少在创建和销毁线程上所花的时间以及系统资源的开销。
  • 将当前任务与主线程隔离,能实现主线程的异步执行。特别是很多可以分开重复执行的任务。

Java线程池的创建方法

  1. newFixedThreadPool,创建一个固定长度的线程池,当达到线程最大数量时,线程池的规模将不再增大。
  2. newCachedThreadPool创建一个可缓存的线程池,如果当前线程池的规模处理需求,将回收空线程。当需求增加时,会增加线程数量,线程池规模无限制。
  3. newSingleThreadPoolExecutor创建一个单线程的Executor,确保任务正确,串行执行
  4. newScheduledThreadPool创建一个固定长度的线程池,而且以延迟或者定时的方式来执行。

代码示例

  1. newFixedThreadPool
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* FixedThreadPoolDemo
*/
public class FixedThreadPoolDemo implements Runnable{
private String name;
public FixedThreadPoolDemo(String name){
this.name=name;
}
@Override
public void run() {
System.out.println(name+"start at:"+new Date());
processCommand();
System.out.println(name+"End at:"+ new Date());
}

private void processCommand() {
try {
Thread.sleep(1000);
} catch (Exception e) {
//TODO: handle exception
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("Main start at: "+new Date());
ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i=0;i<10;i++){
executorService.execute(new FixedThreadPoolDemo(String.valueOf(i)));
}
executorService.shutdown();
System.out.println("Main end at:"+new Date());
}

}

newCatchThreadPool还有newSingleThreadPool用法和上面类似不在赘述newScheduleThreadPool可以设置线程的先后间隔以及执行时间。

submit()方法

将线程放入线程池中,除了使用execute方法,也可以使用submit()。主要区别是一个有返回值,一个没有。submit可以配合Future结合一起使用,可以起到如果线程没有返回结果,就当前线程等待线程池结果返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


/**
* SubmitDemo
*/
public class SubmitDemo implements Callable<String>{

private int id;
public SubmitDemo(int id){
this.id=id;
}

@Override
public String call() throws Exception {
System.out.println("call()方法被调用"+Thread.currentThread().getName());
for(int i=9999;i>0;i++);
return "call()方法被自动调用"+id+Thread.currentThread().getName();
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
for(int i=0;i<10;i++){
Future<String> future = executorService.submit(new SubmitDemo(i));
resultList.add(future);
}
executorService.shutdown();
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}finally{

}
}
}
}

submit的底层源码还是调用了execute()方法。

1
2
3
4
5
6
public <T> Future<T> submit(Callable<T> task){
if(task==null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}