Java并发编程:线程池
什么是线程池,当一个线执行完一个任务后就死亡了,如果程序并发的线程数量非常多,频繁的创建销毁线程会降低执行的效率。
这样,可以创建一些线程,它们的集合称为线程池,当服务器接受到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务完后不关闭该线程,而是将该线程还回到线程池中。
在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,这就是封装。任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。
ThreadPoolExecutor类:
Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
然后ThreadPoolExecutor继承了类AbstractExecutorService。
在ThreadPoolExecutor类中有几个非常重要的方法:
execute()
submit()
shutdown()
shutdownNow()
例子:创建一个线程池,用于执行10个任务。
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
/**
* @param args
*/
public static void main(String[] args) {
// ExecutorService threadPool = Executors.newFixedThreadPool(3);
ExecutorService threadPool = Executors.newCachedThreadPool();
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
for(int i=1; i<=10; i++){
final int task = i;
threadPool.execute(new Runnable(){ //execute 执行一次任务
public void run(){
for(int j=1; j<=10; j++){ // 每个任务输出10次循环
try{
Thread.sleep(20);
} catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + task + " " + new Date());
}
}
});
}
/*
上面的代码是在提交任务,并且所有的任务都已经提交了,但任务是什么时候执行的,则是由线程池调度的!
*/
System.out.println("All of 10 tasks have commited!");
threadPool.shutdown();
//shutdown() 方法在终止前允许执行以前提交的任务,而 shutdownNow() 方法阻止等待任务启动并试图停止当前正在执行的任务。
//shutdown() 拒绝传入任务,执行以提交线程池的任务 shutdownNow() 取消所有遗留任务
//线程池启用定时器线程5s后开始爆炸,每隔2s炸一次
Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable(){ //atFixedRate 在固定的频率
public void run(){
System.out.println("Bombing..." + new Date());
}
},
5,
2,
TimeUnit.SECONDS);
/*
瑕疵 无指定时间点方法 可以使用 要定时的时间-现在的时间
schedule(task,date.getTime()-System.currentTimeMillis(),TimeUnit.MILLISECOUNDS);
*/
}
}
/*
用线程池实现:子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次。
*/
public class ThreadCommunication {
public static void main(String[] args) {
final Business bussiness = new Business();
new Thread(new Runnable(){
public void run() {
for(int i=1; i<=50; i++){
bussiness.sub(i);
}
}
}).start();
for(int i=1; i<=50; i++){
bussiness.main(i);
}
}
}
class Business{
private boolean bShouldSub = true;
public synchronized void sub(int i) {
while(!bShouldSub){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int j=1; j<=10; j++) {
System.out.println("sub thread sequence of " + j + ", loop of " + i );
}
bShouldSub = false;
this.notify();
}
public synchronized void main(int i) {
while(bShouldSub){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int j=1; j<=100; j++) {
System.out.println("main thread sequence of " + j + ", loop of " + i );
}
bShouldSub = true;
this.notify();
}
}