基础概念
程序是为了完成某个特定任务,使用某种计算机语言编写的一组指令的有序集合
进程是具有一定独立功能的程序的运行过程,是系统进行资源分配和任务调度的一个独立单位
线程是进程中的一个独立执行线索,是CPU调度和分配的基本单位,自己基本上不拥有系统资源
进程
每个进程都有独立的代码和数据空间,进程切换成本较高,一个进程中可以包含1-n个线程,进程是资源分配的最小单位
同一个进程中的线程可能会有共享代码,可以共享进程的数据空间,每个线程由独立的运行栈和程序计数器,线程切换的开销很小,线程是CPU调用的最小单位
启动进程
进程和线程一样分为5个阶段:创建、就绪、运行、阻塞和终止
cmd /c启动运行名称后会关闭关闭窗口
启动方法1
ProcessBuilder builder=new ProcessBuilder(“cmd”,"/c",“ipconfig/all”);//构建进程的对象
Process process=builder.start(); //启动进程
//获取ipconfig/all命令的执行结果
BufferedReader reader=new BufferedReader(new InputStreamReader(process.getInputStream(),“GBK”));//用于获取ipconfig/all进程的执行结果
String tmp=null;
while((tmp=reader.readLine())!=null)
System.out.println(tmp);
启动方法2
String cmdStr=“cmd /c ipconfig/all”;
Process process=Runtime.getRuntime().exec(cmdStr);
BufferedReader reader=new BufferedReader(new InputStreamReader(process.getInputStream(),“GBK”));//用于获取ipconfig/all进程的执行结果
String tmp=null;
while((tmp=reader.readLine())!=null)
System.out.println(tmp);
应用
考试系统中生成java代码文件并编译运行
//生成T1.java文件
File f=new File(“T1.java”); //这个类名称也可以通过用户输入查找到
if(f.exists())
f.delete(); //如果T1.java已经存在则删除旧有文件
PrintWriter out=new PrintWriter(new FileWriter(f));
out.println(“public class T1 {”);
out.println(“public static void main(String[] args)throws Exception {”);
out.println(“System.out.println(“Hello java!”);”);
out.println("}}");
out.close();
//编译T1.java,对应的命令为javac T1.java
Process process=Runtime.getRuntime().exec(“cmd /c javac T1.java”);
boolean runnable=true;
//process.getInputStream()获取获取所执行进程的输出信息,注意不是报错信息。如果需要获取报错信息则应该使用process.getErrorStream()。注意javac编译器编译通过实际上是没有响应信息的
BufferedReader br=new BufferedReader(new InputStreamReader(process.getErrorStream()));
while(true){
String tmp=br.readLine(); //整行读取javac编译的报错信息
if(tmp==null)
break; //如果没有报错信息则直接退出循环
System.out.println(tmp);
runnable=false; //告知系统编译失败
}
//如果编译通过则调用解释器java执行T1.class
if(runnable){
process=Runtime.getRuntime().exec(“cmd /c java T1”);
br=new BufferedReader(new InputStreamReader(process.getInputStream()));
//输出执行结果
while(true) {
String tmp=br.readLine();
if(tmp==null)
break;
System.out.println(tmp);
}
}
进程三大特征
独立性:进程是一个能够独立运行的基本单位,是系统资源分配和调度的独立单位
动态性:进程的实质就是程序的一次执行过程,动态的产生、动态的消亡
并发性:任何进程都可以同其它进程一起并发执行
异步性
结构特征:进程由程序、数据和进程控制块三部分构成
僵尸进程和孤儿进程
僵尸进程就是当子进程比父进程先结束,但是父进程没有回收子进程,并没有释放子进程所占用的资源。
父进程先退出,子进程会给init进程接管,子进程退出后init会回收子进程所占用的相关资源
是对系统资源的浪费,测试人员有业务发现,需要处理解决
孤儿进程就是当父进程退出,而多个子进程还在运行
孤儿进程会被init进程管理,并由init进程对其进行状态收集工作
没有什么危害
并行与并发
并行是指多个CPU或者多台机器同时执行一段处理逻辑,是真正的同时执行
并发是指通过CPU调度算法,使用户看上去似乎是在同时执行,实际从CPU操作层面上不是真正的同时执行
主线程
线程是进程中的一个实体,用来描述进程的执行,负责执行包括在进程内部地址空间中的代码
创建一个进程时,它的第一个线程称为主线程,是由系统自动生成的
主线程是产生其它子线程的线程
通常都是最后执行完成的,因为还需要它来执行各种关闭动作。
public class Test1{
public static void main(String[] args)throws Exception{ //当java程序运行时,首先创建一个运行main方法的线程—主线程
System.out.println(Thread.currentThread().getName());//获取运行main方法的线程名称
//在主线程内容可以启动子线程
Thread t=new Thread(){
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
t.start();//启动线程t的运行
System.in.read(); //阻塞当前main线程
}
}
进程中线程之间的关系
一个进程中的线程之间没有父子关系之分,都是平级关系,所有线程都是一样的,一个退出不会影响另外一个。但是在主线程中执行完毕可以使用System.exit(int)强制结束当前进程,exit方法会使整个进程停止,那么所有的线程都会自动退出
进程 vs 线程
一个线程只能属于一个进程,而一个进程可以包含多个线程,至少有一个线程(主线程)
资源调度和分配给进程,同一进程中的所有线程共享该进程的所有资源
线程在执行过程中,共享数据一般都需要进行协作同步
CPU分给线程,真正在处理机上运行的是线程
线程是指在进程内部的一个执行单元,也是进程内的可调度的实体,两者都是动态的概念
进程和线程最大的区别在于:进程是由操作系统来控制的,而线程是由进程来控制
线程本身的数据通常只有寄存器数据以及当前程序在运行时使用的堆栈,所以线程的切换比进程切换的成本要小的多。
多个进程的内部数据和状态是完全独立的,而同一个进程内的多线程共享一块内存空间和一组系统资源,有可能互相影响。
多线程
线程是进程中的一个执行实体,用来描述进程的执行,负责指向包括在进程内部地址空间中的代码
在Java中一个应用可以包含多个线程,每个线程执行特定任务,可以与其它线程并发执行
引入多线程的目标在于减少CPU空转时间,提供CPU的利用率,java多线程提供了一个编程模型隐藏CPU在多任务间切换的实现细节,不需要修改代码就可以实现跨多CPU、多核的处理器
提高吞吐量,充分利用cpu资源,减少cpu空转时间
伸缩性,可以通过CPU核数提升性能。使用多线程并不能提高硬件的性能
注意:在很多情况下可以显式地使用线程以提高程序执行的性能、响应速度。要用多线程的主要原因是运行过程中需要处理大量的IO操作或者需要有较多的等待时间,比如读写文件、视频图像的采集等。
问题1:多线程机制会提高程序的运行效率?
不一定。如果针对密集型计算的应用应该使用单线程,避免多线程中的切换问题,反而引入多线程会影响执行效率
资源限制的挑战。在并发编程时需要考虑到资源上的限制,如果受制于资源,整体程序的速度肯定会降低
解决方案:
对于硬件资源的限制,可以使用集群来执行程序
对于软件资源上的限制,可以通过复用资源的方式提高,例如复用数据库连接
可以根据资源的限制,灵活的调整并发度
多线程优点
在多任务中,各个进程需要分配各自独立的地址空间;多线程可共享相同的地址空间并且分享同一个进程
进程间调用涉及的开销比线程通信多
线程间的切换成本比进程间切换的成本低
多线程的缺点
设计更复杂,上下文切换开销,增加资源消耗
线程
线程是比进程更小的执行单位
线程:轻量级进程LWP,系统负担小,主要是CPU分配
线程不能独立存在,必须存在于进程中
每个线程也都有它产生、存在和消亡的过程,也是一个动态的概念
一个线程有它自己的入口和出口以及一个顺序执行的代码序列
多线程
多线程是指同时存在几个执行体,按几个不同的执行线索共同工作的情况
多线程实现单个进程中的并发计算,JDK1.8开始提供了针对并行支持
各个线程间共享进程空间中的数据,并可以利用共享单元实现数据交换、实时通信与必要的同步操作
多线程的程序可以更好的表述和解决现实世界中的具体问题,是计算机应用开发和程序设计的一个必然趋势
Java与多线程
Java语言内置了对多线程的支持,可以很方便的开发出具备多线程功能,同时处理多个任务的应用。
每个Java应用程序都有一个隐藏的主线程
Application main方法
Applet小应用程序,主线程指挥浏览器加载并执行Java小程序