这里大致分两个部分说明一下,
- 进程,线程,进程池,线程池,多进程和多线程;
- jdk的executor多线程框架。
第一部分:
首先说一下我理解的这几个概念:
- 进程:
系统分配资源的最小单元:也就是说,操作系统是按照一个进程进行分配资源的,每个进程有自己的内存区域,别的进程看不到,这就引出了一个问题,如果我进程A要引用进程B中某个功能,如何实现呢?采用的IPC(Inter-Process Communication),即进程间通信,这里不多说,简单的理解,就是一个应用就是一个进程; - 线程:
线程就是任务执行的最小单元,比如:QQ中,发送消息,查看资料,这些操作,都可以使用一个线程来完成,也就是说,一个进程里是由多个线程来具体完成操作的; - 进程池:
就是预先准备好进程,当你要使用的时候,就不用自己来创建了,直接从预先创建好的进程池里取出就行,进程池里可以是固定数量,或者动态添加的; - 线程池:
由于创建一个线程,要消耗很多资源,比如CPU,内存等,故可以提前创建好一批线程,用来使用。
看到这儿,有人会发现,其实线程池和进程池的概念差不多,到底如何取舍,请看下面的比较:
第二部分:
在jdk中,可以使用executor来进行多线程的使用,主要有下面几个类:
1,executor :接口,多线程中的顶级接口,只有一个 execute(Runnable run) 方法,由参数看出来,用来添加runnable 线程运行;
2,executorService:接口,继承了executor接口,并添加了自己的方法,比如:commit, destroy等等;
3,executors:类,是executor和executorService的工厂类,最常用的有:
Executors.newSingleThreadExecutor():创建单个线程
Executors.newFixedThreadPool(int nThread); 创建固定数量的线程
Executors.newCachedThreadPool(); 动态的创建线程,
具体代码:
MyThread类:
public class Mythread extends Thread{
String name;
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"---在执行");
}
}
Test类:
public class Test{
public static void main(String[] args){
Executor a1 = Executors.newSingleThreadExecutor();
Executor a2 = Executors.newFixedThreadPool(3);
Executor a3 = Executors.newCachedThreadPool();
Mythread t1 = new Mythread();
Mythread t2 = new Mythread();
Mythread t3 = new Mythread();
a1.execute(t1);
a1.execute(t2);
a1.execute(t3);
a2.execute(t1);
a2.execute(t2);
a2.execute(t3);
a3.execute(t1);
a3.execute(t2);
a3.execute(t3);
}
}
结果:
pool-1-thread-1---在执行
pool-2-thread-3---在执行
pool-2-thread-2---在执行
pool-1-thread-1---在执行
pool-1-thread-1---在执行
pool-2-thread-1---在执行
pool-3-thread-1---在执行
pool-3-thread-3---在执行
pool-3-thread-2---在执行
从结果可以看出,a1,newSingleThreadExecutor,只 创建了一个线程,而newFixedThreadPool和newCachedThreadPool都有3个线程在运行,但是newFixedThreadPool显然有劣势,因为他要提前设定好数量,而newCachedThreadPool,会根据你a3.execute(t3); 添加的Thread类,自己创建和回收,显然更好些。