一、为什么有使用多线程进行编程的好处?
1、资源率:可以充分利用系统资源。
2、性能上:设计良好的并发编程可以减少程序的响应时间、提高程序应答效率、降低业务系统的代码开发复杂度。
二、并发编程的坏处?
资源方面需要消耗更多的系统资源,线程在切换、管理堆栈,变量空间方面就需更多额外的资源来控制, 在功能测试方面会增加复杂度,如果出现不好的代码会导致修复方面的复杂度大大增加。
三、什么是进程、线程?
进程指的是负责整个程序的运行,程序通信进行数据调集的一次运行活动,也是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
线程指的是进程中的一个基础组成单元,一个进程可拥有多个线程
四、单线程是什么 ?
在一个程序中,我们启动一个进程,只有一个主线程 main线程,外界发起请求调用需要串行的响应,一次请求未完成则会阻塞后面的数据请求。
五、多线程又是什么?
在一个程序中,我们启动一个进程,使用多条线程同时进行业务数据的交互。
六、多线程开发(并发编程)需要注意的是什么?
1、线程安全性:在多线程的环境下,我们对共享成员变量等数据进行访问和数值修改是需要同步通知、在各个调用共享变量的线程实时更新,所以我们需要使用到Java的同步机制。
2、性能问题:
线程上下文切换不可过于频繁, 如果上下文切换频繁,CPU花在上下文切换上的时间占比就会上升,而真正处理任务的时间占比就会下降。
要设计良好的并发程序,否则在响应时间、系统利用率、吞吐率、代码响应灵敏度造成极大的错误
应当尽量减少程序中的线程数量,如果可以的话,可尝试无锁并发编程。
要避免死锁,第一不要在一条线程中嵌套使用多个锁,第二不要在一条线程中嵌套占用多个计算机资源;第三最好给锁和资源加超时时间;如果你非要在一条线程中嵌套使用多个锁或占用多个资源,那你需要给锁、资源加超时时间,从而避免无限期的等待。
七、Java 并发编程的实现方式有哪些?
1、继承Thread的方式
线程类继承Thread类,调用start()方法来启动线程,真正实现了多线程运行。实现run()方法来调用你的业务代码。
2、声明实现 Runnable接口的方式
Runnable接口的实现类,并重写其中的run方法。run()方法的方法体是线程执行体。
a、Thread方式,使用synchronized关键字。
synchronized关键字可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
应用于普通同步方法时,锁是当前实例对象;静态同步方法时,锁是当前类的class对象;同步方法块,锁是括号里面的对象。
运行的结果:
从结果来看: 多线程的情况下,貌似synchronized没起作用。
为什么尼?因为上面每个线程都 new SynchronizedTest() 这是五个不同的对象,所以可以多线程同时运行synchronized方法或代码段。实际上,synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段。
所以synchronized锁住的是括号里的对象,而不是代码。那么对于非static的synchronized方法,锁的就是对象本身也就是this。
所以使用synchronized关键字的时候,应当尽量缩小代码块的应用范围,可以再代码片段中加同步就不要扩展到方法上面去,而且对于整体多线程来说 代码片段锁定的时间上来说也会相应的缩短了一些。
结果上看就是完成了同步
因为你需要锁的是对象,同步就完成了。那么也可以这样做
也可以达到一样的效果。
使用静态方法的话
也可以达到一样的效果。
二、实现Runnable的方式的多线程
synchronzied关键字它不能尝试获取锁,也不响应中断,还可能会死锁。不过,相比显式锁,synchronized简单易用,JVM也可以不断优化它的实现,应该被优先使用。显式锁是相对于synchronized隐式锁而言的,它可以实现synchronzied同样的功能,但需要程序员自己创建锁,调用锁相关的接口,主要接口是Lock,主要实现类是ReentrantLock。
相比synchronized,显式锁支持以非阻塞方式获取锁、可以响应中断、可以限时、可以指定公平性、可以解决死锁问题,这使得它灵活的多。
在读多写少、读操作可以完全并行的场景中,可以使用读写锁以提高并发度,读写锁的接口是ReadWriteLock,实现类是ReentrantReadWriteLock。
二、使用volatile关键字
被 volatile 修饰的共享变量:
第一它保证了不同线程对这个变量进行读取时的可见性,也就是解决了可见性问题。含义大概就是一个线程修改了某个变量的值,修改后的这个新值对于其他调用它的线程来说是立即被通知到,所以是可见的。
第二它禁止进行指令重排序, 阻止编译器对代码的优化。 加入 volatile 关键字时, 编译器在生成字节码时,会在指令序列中插入内存屏障, 会多出一个 lock 前缀指令。 内存屏障是解决禁止指令重排序和可见性问题。
结果是:
网友评论