------- 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个方法以及多线程的安全解决方式(同步代码块和同步函数)等等都做了一一总结,希望能对自己和大家提供些小小的帮助..
饿汉式,是我建议写单例时,所使用的方式,因为它没有线程安全上的问题..
但懒汉式,具有线程安全上的问题,通过对以上线程的学习,我来解决下懒汉式的线程安全问题:
以上的懒汉式,只要将函数同步,就解决了多线程的安全问题..
但如果,线程过多的情况下,每一个线程都要判断次锁,比较低效,所以还有比较高效的解决方案: