前提:关于为啥要有进程?
因为系统支持多任务,需要并发编程,通过多进程就可以实现并发编程,但是又问题~
创建进程需要分配资源(内存资源、文件资源),销毁进程还需要释放资源,对于资源的申请和释放又是一个非常低效的操作,如果频繁的调度进程,成本是比较高的~
如何解决低效这个问题呢?
方法一:进程池:(数据库连接池、字符串常量池)
申请完之后并不进行真正的释放,只是把它归还到池里,下次再使用进程时直接去池
里拿,跳过申请释放的过程 ,这时整体的开销就大大降低了
虽然进程池能解决上述问题,提高效率,但是使用进程池也存在着一定的问题,就是消耗的系统资源太多了,因为进程池里的闲置进程,不使用时也在消耗着系统资源(不适用于资源紧张的情况)
方法二:使用线程来实现并发编程:
原因:线程比进程更轻量,每个进程可以执行一个任务,每个进程也能执行一个任务,也能够并发编程
创建线程的成本比创建进程要低很多,销毁线程的成本也比销毁进程低很多,调度线程的成本也比调度进程低很多
为什么线程比进程更轻量?
进程重量是重在资源的申请和释放,而线程是包含在进程中的,一个进程中的多个线程,公用同一份资源(内存+文件),只是在创建进程的第一个线程的时候(由于要分配资源),成本是相对高的,后续这个进程中再创建其他线程,这个时候成本会更低些(因为不必再分配资源了)
可以把进程比作一个工厂,假设这个工厂要生产1W部手机
要想提高生产效率:
1、搞两个工厂,一个工厂生产5K部手机(相当于多创建了一个进程)
2、还是一个工厂,在一个工厂里多加一个生产线,两个生产线并行生产,一个生产线生产5K部手机(相当于多创建了一个线程)
最终生产1W部手机,用这两个办法花 的时间都差不多,但是成本上就有差异了
用第一种方法建公厂的话,需要新搞场地、新盖厂房……准备各种各样的东西,全都准备好了才能投入生产,但是用第二种方法,新加一个生产线,此时就不用再准备厂房啥的了,直接都是现成的,场地也是现成的……啥都不用准备,只需要一个新的生产线就可以了
此时可以发现搞线程比搞进程更高效~
但是不是加线程加的越多,效率就越快的,因为整体的硬件资源是有限的,如果线程很多,这些线程可能要竞争同一个资源,这时候整体的速度就受到了限制
进程和线程的区别和联系:(重点)
1、进程包含线程,一个进程里可以有一个线程,也可以有多个线程
2、进程和线程都是为了处理并发编程这样的场景。但进程有问题,就是在频繁的创建和释放的时候效率低,相比之下,线程更轻量,创建和释放效率更高(轻量的原因:少了申请释放资源的过程)
3、操作系统创建进程,要给进程分配资源,进程是操作系统分配资源的基本单位
操作系统创建线程,是要在CPU上调度执行,线程是操作系统调度执行的基本单位
4、进程具有独立性,每个进程有各自的虚拟地址空间,一旦进程挂了,不会影响到其他进程
同一个进程中的多个线程,共用同一个内存空间,一个线程挂了,可能影响到其他线程,甚至导致整个进程崩溃
在Java标准库中,提供的Thread来表示/操作线程
Thread类可视为是Java标准库提供的API
创建好的Thread实例,和操作系统中的线程是一一对应的关系
(因为操作系统提供了一组C语言风格的关于线程的API,Java对于这组API进一步封装成Thread类)
关于Thread类创建线程的具体方法:
方法一:创建一个继承Thread的子类,并重写run方法
class MyThread extends Thread{//创建Thread子类,相当于自己写的MyThread类针对标准库中的Thread类进行进一步的扩展 @Override public void run() {//在这个方法里写这个线程里具体执行的代码 System.out.println("hello thread"); } } //最基本的创建线程的方法 public class Demo1 { public static void main(String[] args) { Thread t=new MyThread(); //new一个Thread的子类,换句话说在创建线程时,需要线创建一个子类继承自Thread,然后才能进行使用 t.start();//此时系统才创建了线程,调用start之前系统中是没有创建线程的 } }
注意:
1.run方法中写的是在新创建的线程中要被执行的代码,并不是代表写完这个run方法,线程就创建好了(相当于把活安排好了,但是还没开始干)
2.需要调用start方法,此时才真正的在系统中创建了线程,才真正开始执行run操作,在调用start之前,系统中是没有创建出线程的
并发执行线程:
自己创建的 t 线程和自动创建的 main 线程(在java进程中,至少会有一个调用main方法的线程),就是并发执行的关系(宏观上看起来是同时执行)
class MyThread2 extends Thread{ @Override public void run() { while(true){//无限循环 System.out.println("hello thread"); try { Thread.sleep(1000);//1s中打印一下 } catch (InterruptedException e) {//多线程中常见异常-》线程被提前中断了,这里是执行sleep操作抛出的异常 } } } } public class Demo2 { public static void main(String[] args) { Thread t=new MyThread2();//自己创建的t线程 t.start();//此时创建好t线程