Java多线程

2018-07-30  本文已影响0人  会九卦的兔子

一、为什么有使用多线程进行编程的好处?   

    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 前缀指令。 内存屏障是解决禁止指令重排序和可见性问题。

结果是:

上一篇下一篇

猜你喜欢

热点阅读