------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
黑马程序员—多线程
线程:其实就是进程中一个程序执行控制单元,一条执行路径。进程负责的是应用程序的空间的标示。线程负责的是应用程序的执行顺序。
进程:正在进行中的程序。其实进程就是一个应用程序运行时的内存分配空间。一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区、自己的变量。
jvm在启动的时,首先有一个主线程,负责程序的执行,调用的是main函数。主线程执行的代码都在main方法中。
当产生垃圾时,收垃圾的动作,是不需要主线程来完成,因为这样,会出现主线程中的代码执行会停止,会去运行垃圾回收器代码,效率较低,所以由单独一个线程来负责垃圾回收。
随机性的原理:因为cpu的快速切换造成,哪个线程获取到了cpu的执行权,哪个线程就执行。
可以理解成多个线程在抢 cpu 资源
多线程下载:此时线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开起好几个下载通道.当服务器提供下载服务时, 使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配。不难理解,如果你线程多的话,那下载的越快。现流行的下载软件都支持多线程。
多线程是为了同步完成多项任务,不是为了提供运行效率,通过提高资源使用效率来提高系统的效率。
线程是在同一时间需要完成多项任务的时候实现的.
返回当前线程的名称:Thread.currentThread().getName()
线程的名称是由:Thread-编号定义的。编号从0开始。
线程要运行的代码都统一存放在了run方法中。
线程与进程的比较
线程具有许多传统进程所具有的特征, 故又称为轻型进程(Light—Weight Process)或进程元;而把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有一个线程的任务。
在引入了线程的操作系统中,通常一个进程都有若干个线程,至少需要一个线程。
进程与线程的区别:
1.进程有独立的进程空间,进程中的数据存放空间(堆空间和栈空间)是独立的。
2.线程的堆空间是共享的,栈空间是独立的,线程消耗的资源也比进程小,相互之间可以影响的。
创建线程的种方式:
继承Thread,由子类复写run方法。
步骤:
1,定义类继承Thread类;
2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;
3,通过创建Thread类的子类对象,创建线程对象;
4,调用线程的start方法,开启线程,并执行run方法。
创建线程的第二种方式:
实现一个接口Runnable。
步骤:
1,定义类实现Runnable接口。
2,覆盖接口中的run方法(用于封装线程要运行的代码)。
3,通过Thread类创建线程对象;
4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。
为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
Thread 类中 run()和 start()方法的区别如下:
run()方法:在本线程内调用该 Runnable 对象的 run()方法,可以重复多次调用;
start()方法:启动一个线程,调用该 Runnable 对象的 run()方法,不能多次启动一个线程;
两种进程创建方式比较
A extends Thread:
简单
不能再继承其他类了(Java 单继承)
同份资源不共享
A implements Runnable:(推荐)
多个线程共享一个目标资源,适合多线程处理同一份资源。
该类还可以继承其他类,也可以实现其他接口。
实现方式,因为避免了单继承的局限性,所以创建线程建议使用第二种方式。
多线程安全问题
解决办法:导致安全问题的出现的原因:
多个线程访问出现延迟。
线程随机性。
注:线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。
我们可以通过 Thread.sleep(long time)方法来简单模拟延迟情况。
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。 导致共享数据的错误。
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不 可以参与执行。
多线程安全问题的解决方法
三种方法:
同步代码块:
synchronized(obj)
{
//obj 表示同步监视器,是同一个同步对象
/**.....
TODO SOMETHING
*/
}
同步方 法;
格式:
在方法上加上 synchronized 修饰符即可。 (一般不直接在 run 方法上加! )
synchronized 返回值类型 方法名(参数列表)
{
/**.....
TODO SOMETHING
*/
}
同步方法的同步监听器其实的是 this格式:
在方法上加上 synchronized 修饰符即可。 (一般不直接在 run 方法上加! )
synchronized 返回值类型 方法名(参数列表)
{
/**.....
TODO SOMETHING
*/
}
同步方法的同步监听器其实的是 this
静态方法的同步
同步方法
同步代码块
static 不能和 this 连用
静态同步默认的锁是当前class文件对应的字节码文件