黑马程序员_java的多线程(对第十一课创建多线程及多线程安全问题总结)

------- android培训java培训、期待与您交流! ----------


通过今天对java语言多线程的学习,我来给自己的学习内容做下简单直白的总结:

首先,我来总结下什么是线程:

在总结线程之前,我们先来了解下进程,所谓进程,简单点来说也就是一个正在执行中的程序...那么进程在执行的时候,都会有一个执行顺序,该循序是一个执行路径,也可以称为一个控制单元...打个比方来说:搬运货物这件事,就相当于是一个进程...

而线程:就是进程中的一个独立的控制单元,进程的执行是有线程来控制的,那么,进程中最少有一个线程....

打个比方来说:如果搬运货物这件事,相当于是一个进程,那么搬运货物的每一个过程,就相当于线程...

最后个人认为:进程就相当于是一个程序,而线程在控制着该程序,一步一步的执行程序中的代码,来实现该程序..


java虚拟机在启动的时候,会有一个进程:java.exe...在该进程中,至少有一个线程在负责程序的执行,该线程执行的代码存放在main方法中,该线程也可以称为主线程...

在java中,如果只有一个线程在负责程序的执行,我们称之为:单线程...那么可以看出,如果一个进程中,有2个或2个以上的线程在执行,那么我们就可以称之为:多线程...

多线程存在的意义:

多线程出现:可以让一个程序中的某些部分产生同时运行的效果.提高了效率(就是可以使程序中的多部分代码同时执行)



多线程的创建:.如何在自定义的代码中,自定义一个线程呢...有2种方式:

通过API的查找,java已经提供好了对线程这类事物的描述,就是Thread类....

那么创建线程的第一种方式:

1,我们可以定义一个类来继承Thread类,来加入该体系中...

2,该子类要复写Thread类的run方法,因为它里面存储的都是线程要运行的代码,线程最终执行的内容都在run方法中

3,调用线程的start方法...

注意:当用start方法的时候,该方法做了2步:开启线程和自动调用run方法....



多线程的一个特性:随机性

因为有了多线程,发现每次的运算结果都不同...是因为多个线程都在抢夺cpu的执行权,cpu切换到哪个线程,哪个线程就执行(其实就是cpu在做着快速的切换动作),我们可以形象的把多线程的运行行为称为互相抢夺cpu执行权..


多线程的运行状态示例图:

通过多线程的运行的示例图,能更方便的让我们理解多线程在运行的时候的一些状态..

通过上图,我们可以看出:

具有执行资格,又有执行权的是运行状态..

具有执行资格,没有执行权的是运行状态..

没有执行资格,也没有执行权的是冻结状态..


创建线程的第二种方式:实现Runnable接口..

因为Thread线程类实现过Runnable接口,在Thread类的构造函数中,可以接受一个Runnable接口的对象,当Thread类调用start方法时,会开启线程,并去调用Runnable接口对象里的run方法来执行..所以,我们可以按步骤:

1,创建一个类,实现Runnable接口...并覆盖Runnable接口中的run方法...

2,通过Thread类来建立线程对象...

3,将Runnable接口的子类对象(父类引用指向子类对象),作为实际参数传递给Thread类的构造函数..

3,调用Thread类的start方法..(它会开启线程,并调用Runable接口的子类对象中的run方法,让线程去执行)


创建线程的第一种继承方式和创建线程的第二种实现方式 有什么区别:

实现方式:它避免了类只能单继承的局限性..

在定义线程时,建议使用实现方式..

存放运行代码的位置也不一样:

继承:线程的运行代码存放在Thread子类的run方法中..

实现:线程的运行代码存放在Runnable接口子类的run方法中...



下面来总结个重点,在多个线程的运行中,有可能会出现一定的安全问题..比如:

当多条语句(if等等)在操作N个线程的共享数据时,一个线程进来只执行了一部分,没有执行完,而另一个线程又参与了进来执行,会导致共享数据的错误...

那么,我们该如何去解决:当多条语句在操作N个线程的共享数据时,我们可以让一个线程进来执行,在它的执行过程中,另一个线程不可以参与进来执行...就相当于,至始至终就只有一个线程在里面执行,让其它的线程都在外边等待..


最后:问题的解决办法有了,那在java中,怎么去体现呢:java给我们提供了专业的语句来体现:就是同步代码块..

同步代码块的体现格式:synchronized(对象(或叫锁)){需要被同步的代码}

注意:哪些代码需要被同步,就看哪些语句是被N个线程所共享的...

对象如同锁,只有持有锁的线程可以在同步中执行,没有持有锁的线程,即使有执行权,也进不来..

重要扩展:同步的前提:

1,必须是2个或2个以上的线程...

2,必须是多个线程使用的是同一把锁...

这样,同步代码块就解决了多线程的安全问题...但是,多了一层判断,多个线程都需要去判断次锁,消耗了资源...


我们不仅仅可以使用同步代码块,还可以使方法具备同步的特性:同步函数

当方法内部,没有多余的操作语句,只有多个线程的共享数据时,我们可以把该函数加上同步的特性...

同步非静态函数所使用的锁是this...

同步静态函数所使用的锁是字节码文件对象...(静态函数中不能使用this),类名.class,该对象的类型是Class...



通过本课的学习,以上我多线程的定义,创建多线程的2个方法以及多线程的安全解决方式(同步代码块和同步函数)等等都做了一一总结,希望能对自己和大家提供些小小的帮助..


扩展:在前面我的学习总结中,有总结过单例设计模式,单例设计模式有2种方式,一种是饿汉式,一种是懒汉式...

饿汉式,是我建议写单例时,所使用的方式,因为它没有线程安全上的问题..

但懒汉式,具有线程安全上的问题,通过对以上线程的学习,我来解决下懒汉式的线程安全问题:


以上的懒汉式,只要将函数同步,就解决了多线程的安全问题..


但如果,线程过多的情况下,每一个线程都要判断次锁,比较低效,所以还有比较高效的解决方案:








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值