-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
1:要想了解多线程,必须先了解线程,而要想了解线程,必须先了解进程,因为线程是依赖于进程而存在。
2:什么是进程?
通过任务管理器我们就看到了进程的存在。
而通过观察,我们发现只有运行的程序才会出现进程。
进程:就是正在运行的程序。
进程是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。
3:多进程有什么意义呢?
单进程的计算机只能做一件事情,而我们现在的计算机都可以做多件事情。
举例:一边玩游戏(游戏进程),一边听音乐(音乐进程)。
也就是说现在的计算机都是支持多进程的,可以在一个时间段内执行多个任务。
并且呢,可以提高CPU的使用率。
问题:
一边玩游戏,一边听音乐是同时进行的吗?
不是。因为单CPU在某一个时间点上只能做一件事情。
而我们在玩游戏,或者听音乐的时候,是CPU在做着程序间的高效切换让我们觉得是同时进行的。
4:什么是线程呢?
在同一个进程内又可以执行多个任务,而这每一个任务我就可以看出是一个线程。
线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。
单线程:如果程序只有一条执行路径。
多线程:如果程序有多条执行路径。
5:多线程有什么意义呢?
多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。
程序的执行其实都是在抢CPU的资源,CPU的执行权。
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到CPU的执行权。
我们是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。
进程:
正在运行的程序,是系统进行资源分配和调用的独立单位。
每一个进程都有它自己的内存空间和系统资源。
线程:
是进程中的单个顺序控制流,是一条执行路径
一个进程如果只有一条执行路径,则称为单线程程序。
一个进程如果有多条执行路径,则称为多线程程序。
大家注意两个词汇的区别:并行和并发。
并行:是逻辑上同时发生,指在某一个时间段内同时运行多个程序。
并发:是物理上同时发生,指在某一个时间点同时运行多个程序。尤其是指多个线程同时访问同一资源时。
Java程序的运行原理:
由java命令启动JVM,JVM启动就相当于启动了一个进程。
接着有该进程创建了一个主线程去调用main方法。
思考题:
jvm虚拟机的启动是单线程的还是多线程的?
多线程的。
原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。
现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。
多线程的实现方式1:
1,线程:在类库中,被封装为:Thread类。
Thread类就是:程序中的执行线程。
创建线程步骤:
A:自定义类MyThread继承Thread类。
B:MyThread类里面重写run()?
为什么是run()方法呢?
C:创建对象
D:启动线程-->调用该对象的start()方法。注意:只有调用start()方法才是启动线程,调用run()方法,只能是一般的普通方法。
多线程程序实现的方式2:
1.实现Runnable接口;
2.重写run()方法;
3.启动线程:
1).实例化我们自定义类的对象;
2).实例化一个Thread对象,并用自定义对象做参数;
3).调用Thread对象的start()
如何获取和设置线程名称?
public final String getName():获取线程的名称。
默认的线程名称格式:Thread-索引
如何设置线程对象的名称呢?
public final void setName(String name):设置线程的名称
针对不是Thread类的子类中如何获取线程对象名称呢?
public staticThread currentThread():返回当前正在执行的线程对象
Thread.currentThread().getName():获取任意方法所在的线程名称
我们的线程没有设置优先级,肯定有默认优先级。
那么,默认优先级是多少呢?
如何获取线程对象的优先级?
public final intgetPriority():返回线程对象的优先级
如何设置线程对象的优先级呢?
public final void setPriority(int newPriority):更改线程的优先级。
注意:
线程默认优先级是5。
线程优先级的范围是:1-10。
线程优先级高仅仅表示线程获取的 CPU时间片的几率高,线程的优先级依赖于操作系统的调度,并不能保证优先级高的线程一定会先执行完毕; 所以,我们不要依赖于"线程的优先级"去让某个线程先执行完毕!如果线程内部的业务逻辑很简单,那么线程的优先级将看不出效果;
IllegalArgumentException:非法参数异常。
抛出的异常表明向方法传递了一个不合法或不正确的参数。
线程控制:
线程休眠
public staticvoid sleep(long millis)
线程加入:
public final void join()等待该线程终止。
线程礼让:
public static void yield():暂停当前正在执行的线程对象,并执行其他线程。 (让当前线程退回到就绪状态,同其他线程一样,一起等待操作系统分配资源,很可能刚刚被yield的线程会立即被CPU重新分配执行, 调用yield()不保证线程会最后执行完毕)。
守护线程:
回想一下我们之前的线程,当主方法结束时,主线程开出的线程仍然继续运行,直到运行完毕;
这个就是:非守护线程;开出的线程不会守护我们的主进程;
可以设置线程为:守护线程:setDeamon(true):它将守护主进程,如果主进程结束,守护线程会跟着结束,
(但不会立即结束,会有个小缓冲);
默认情况下,开出的线程都是:非守护线程;
线程中断:
在主进程中可以结束某个线程:
方式一:stop();(已过时)
方式二:interrupt()(建议使用):当线程处于:Object--wait()及Thread的--join()以及Thread--sleep()受阻时,此方法调用将会导致上述三个方法阻塞时的异常抛出;
线程的生命周期:
新建:创建线程对象
就绪:有执行资格,没有执行权
运行:有执行资格,没有执行权
阻塞:由于一些操作让线程处于该状态,没有执行资格,没有执行权
而另一些操作却可以把它给激活,激活后处于就绪状态。
死亡:线程对象变成垃圾,等待被回收。
线程安全问题:(synchronized)
如何解决线程安全问题呢?
要想解决问题,就要知道哪些原因会导致出问题:(而且这些原因也是以后我们判断一个程序是否会有线程安全问题的标准)
A:是否是多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
我们来回想一下我们的程序有没有上面的问题呢?
A:是否是多线程环境 是
B:是否有共享数据 是
C:是否有多条语句操作共享数据 是
由此可见我们的程序出现问题是正常的,因为它满足出问题的条件。
接下来才是我们要想想如何解决问题呢?
A和B的问题我们改变不了,我们只能想办法去把C改变一下。
思想:
把多条语句操作共享数据的代码给包成一个整体,让某个线程在执行的时候,别人不能来执行。
问题是我们不知道怎么包啊?其实我也不知道,但是Java给我们提供了:同步机制。
同步代码块:
synchronized(对象){
需要同步的代码;
}
A:对象是什么呢?
我们可以随便创建一个对象试试。
B:需要同步的代码是哪些呢?
把多条语句操作共享数据的代码的部分给包起来
注意:
同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。多个线程必须是同一把锁。
同步的特点:
前提:
多个线程
解决问题的时候要注意:
多个线程使用的是同一个锁对象
同步的好处:
同步的出现解决了多线程的安全问题。
同步的弊端:
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
A:同步代码块的锁对象是谁呢?
任意对象。
B:同步方法的格式及锁对象问题?
把同步关键字加在方法上。
同步方法是谁呢?
this
C:静态方法及锁对象问题?
静态方法的锁对象是谁呢?
类的字节码文件对象。(反射会讲)
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------