并行和并发:
并行:指两个或者多个事件在同一时刻发生;
并发:指两个或者多个事件在同一个时间段内发生。
在操作系统中,在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时进行,但在单CPU系统中,每一个时刻却只能有一道程序在执行,故微观上这些程序只能是分时地交替进行。倘若计算机中有多个CPU,则这些可以并发执行的程序便可被分配到多个处理器上,实现多任务并行执行,即利用每个处理器来处理一个可并发执行的程序便可以被分配到多个处理器上,实现多任务并行,所以大家在使用电脑的时候感觉是多个程序同时执行的。
多核是可以同时并行地处理多个程序,从而提高电脑的效率。
单核处理器只能做到并发执行。
同理线程也是一样,从宏观角度上理解线程时并行运行的,但是从微观角度上看又是串行运行的,即一个线程一个线程的去执行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为线程的调度。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
进程和线程概念:
进程是指一个内存中运行中的程序,每个进程都有自己独立的一块内存空间,一个应用程序可以同时启动多个进程。
线程是指进程中的一个执行任务(控制单元),一个进程可以同时并发运行多个线程,如:多线程下编程,一个进程至少有一个线程,为了提高效率,可以在一个进程中开启多个执行任务,即多线程。
多进程:操作系统中同时运行的多个程序
多线程:在一个进程中同时执行的多个任务
在操作系统中允许多个任务,每一个任务就是一个进程,每一个进程也可以同时执行多个任务,每一个任务就是一个线程
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
进程和线程的区别:
进程:有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少有一个线程。
线程:堆空间是共享的,栈空间是独立的。线程小号的资源比进程要小,相互之间可以影响,所以又称为轻型进程或者进程元。
因为一个进程中的多个线程时并发执行的,那么从微观的角度上考虑也是有先后顺序的,那么哪一个线程执行完全取决于CPU的调度器(JVM)。
我们可以把多线程并发性看做多线程在瞬间抢夺CPU的资源,谁抢到资源谁就运行,这也就造就了多线程的随机性。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
线程调度:
计算机通常只有一个CPU时,在任意时刻只能执行一条计算机指令,每一个进程只有获得CPU的使用权才能执行指令。
所谓多进程并发运行,从宏观上看,其实是各个进程轮流获得CPU的使用权,分别执行各自的任务。
那么,在运行池中,会有多个线程出于就绪状态等到CPU,JVM就负责了线程的调度
JVM采用的是抢占式调度,没有采用分时调度,因此,可能造成多线程执行结果的随机性。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
多线程优势:
多线程作为一种多任务,并发的工作方式,当然存在其优势。
1.进程之前不能共享内存,而线程之间共享内存
2.系统创造进程时需要为该进程重新分配系统资源,创造线程则代价小很多,因此实现多任务并发时,多线程的效率更高
3.java语言本身内置多线程功能的支持,而不是单纯地作为底层系统的调度方式,从而简化了多线程编程。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Java中运行一个进程
方式1:Runtime类的exec方法
方式2:ProcessBuilder的start方法
例 : day05 j01
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
创建和启动线程,传统有两种方式:
方式1:使用Thread类: day05 j02
1.定义一个类A继承于 java.lang.Thread类
2.在A类中覆盖Thread类中的run方法。
3.我们在run方法中编写需要执行的操作------》run方法里的线程执行体
4.在main方法中,创建线程对象,并启动线程
创建线程类: A类 a = new A类();
调用线程对象的start方法: a.start() ; // 启动一个线程。
注意:千万不要调用run方法,如果调用了run方法就好比是对象调用方法,依然还是只有一个线程并没有开启新的线程
方式2:实现Runnable接口: day05 j03
1.定义一个类A实现于java.lang.Runnable接口,(注意A类不是线程类)
2.在A类中覆盖Runnable接口中的run方法
3.我们在run方法中编写要执行的操作-----》run方法里的内容是线程执行体
4.在main方法中,创建线程对象,并启动线程。
创建线程类:Thread t = new Thread(new A());
调用线程对象的start方法:t.start();
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
匿名内部类创建线程: day05 j04
一般情况下我们使用接口的匿名内部类
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
继承方式和实现方式的区别: day05 j05
继承方式:
1.Java中类是单继承的,如果继承了Thread,该类就不能再有其他的直接父类了
2.从操作上分析,继承方式更简单,获取线程名字也简单
3.从多线程共享同一个资源上分析,继承方式不能做到。
实现方式:
1.Java中类可以实现多接口,该类还可以继承其他的类,并且实现其他的接口(在设计上更优秀)
2.从操作上分析,实现方式稍微复杂点,获取线程名字也比较复杂,得使用Thread.currentThread()来获取当前线程的引用
3.从多线程共享一个资源上分析,实现方式可以做到
所以:当要共享一个资源的时候,使用实现方式才行,如果不用共享一个资源,那么就不用一定要使用实现方式。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
要解决多线程并发访问多一个资源的安全性问题:
解决方案:
1.同步代码块 day05 j06
语法:
synchronized(同步锁)
{
需要同步操作的代码
}
同步锁:
为了保证每个线程都能正常执行原子操作,java引入了线程同步机制,
同步监听对象/同步锁/同步监听器/互斥锁:
对象的同步锁只是一个概念:可以想象为对象上标记了一个锁
java程序运行使用人户对象作为同步监听对象,一般的,我们把当前并发访问的共同资源作为监听对象
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着。
2.同步方法 day05 j06
使用sychronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在外面等着。
sychronized public void doWork(){}
同步锁:
对于非static方法,同步锁就是this
对于static方法,我们使用当前方法所在类的字节码对象
注意:不要使用sychronized修饰run方法,修饰之后,某一个线程就执行完了 所有的功能。
3.锁机制 day05 j06
lock机制提供了比sychronized代码块和sychronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能lock都有,除此之外更强大,更体现面向对象
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
sychronized的好与坏
好处:保证了多线程并发访问时的同步操作,避免线程的安全性问题。
缺点:使用sychronized的方法或者代码块的性能比不是用的要慢一些
建议:尽量减少sychronized的作用域
StringBuffer 和StringBuilder相比较
StringBuffer慢一点,因为加了sychronized