------- android培训、java培训、期待与您交流! ----------
1)线程的理解:
进程:正在进行的程序(直译)。
线程:进程中一个负责程序执行的控制单元或者执行路径,一个进程至少有一个线程。
多线程:在一个进程中要同时运行多部分代码,故在一个进程中完成同时多次执行,我们称为多线程。Cpu进行切换是随机的。
多线程好处与弊端:好处:解决多部分内容同时执行的问题。弊端:当开启了太多的线程,会导致单个程序运行效率的降低。
JVM启动的时候,至少有两个线程:
①执行main函数的线程
②负责垃圾回收的线程
2)创建多线程的步骤:
第一种方式:继承Thread类
①自定义一个类继承Thread类
②覆盖Thread类中的run方法,并将线程的任务代码封装到run方法中
③直接创建Thread的子类对象来创建线程
④调用start方法开启线程并调用线程的任务run方法执行
问题:调用run方法与调用start方法有什么区别?
答:单独调用run是单线程调用,而调用start的同时会调用run(隐藏),这是多线程
第二种方式:实现Runnable接口
①定义类实现Runnable接口
②覆盖接口中的run方法,并将线程的任务代码封装到run方法中
③调用Thread类创建对象,并将Runnable的子类对象作为构造函数的参数进行传递,为什么?
答:因为线程的任务都封装在Runnable接口的子类对象的run方法中,所以要在线程对象创建时明确要运行的任务。其实这种传参方式运用的原理就是内部类的原理
④调用线程对象的start方法开启线程
第二种方式的好处:这一种方式较为常用
①将线程的任务从线程的子类中分离出来,封装成对象
②避免了单继承的局限性。
3)线程的四种状态:
Java中的线程有四种状态分别是:运行、就绪、挂起、结束。
线程状态图
4)多线程安全问题产生的原因:
①多个线程操作共享的数据。
②操作共享数据的线程代码有多条。
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算。就会导致安全问题的产生。
解决思路:就是将多条操作共享数据的线程代码封装起来,当有线程执行这些代码的时候,其他线程不可以参与运算。在java中,用同步代码块或者同步函数就可以解决这个问题,其格式是:
Syncronized(对象名)//这个对象可以是任意的,一般而言我们都用Object对象
{
需要被同步的代码
}
Public synchronized void 函数名(){//同步代码块中的同步锁是默认的this对象,所以当我们既使用同步代码块又使用同步函数时,将同步代码块的对象换成this就可以了。
需要被同步的代码
}
静态的同步函数使用的锁是该函数所属字节码文件对象,可以用类名.class获取
在使用多线程的过程中,可能会遇到多线程的一种异常叫做InterruptedException异常,由于在Runnable中没有抛出该异常,所以只能使用try-catch来处理该异常。
同步的好处:解决了线程中的安全问题
同步带弊端:相对得降低了效率,因为同外的线程都会判断同步锁。同步的代码越多,线程的执行效率越低。
同步的前提:必须有多个线程并且使用同一个锁。
5)死锁:
死锁的前景之一:同步的嵌套。
6)线程间通信:多个线程在处理同一个资源,可是任务却不同。
线程间通信之等待唤醒机制:使用wait()与notify()
7)多生产者多消费者问题:
在多生产者,多消费者中如果我们按照简单的线程间通信来编代码的话,会出现生产出来的产品会有剩余或者生产的产品不够消费者使用以及死锁的情况,在此过程中,我们可以将if改为while以及将notify()改为notifyAll(),就能够解决问题。
While解决了线程获取执行权后是否要运行的问题。
notifyAll解决了本方线程一定会唤醒对方线程的问题。
8)jdk1.5后新特性:
Jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显式动作,并将object中的监听器也封装成了对象
lock锁:替代同步代码块与同步函数,将隐式锁操作变为显式锁操作,同时更为灵活,一个锁中可以有多个监听器。
lock():获取锁
unlock():释放锁,通常需要定义在finally代码块中
Condition接口:出现了替代了Object的wait(),notify()和notifyAll(),将这些监听器进行单独的封装,编程condition监听器对象。可以和任意锁进行组合。包括await(),singnal(),singnalAll()
9)wait()和sleep()的区别:
①wait可以指定时间,也可以不指定时间,而sleep必须指定时间
②在同步里面,对cpu和锁的处理不同。
wait:释放执行权,释放锁
sleep:释放执行权,不释放锁
10)停止线程的方法:一般使用标记来终止线程。
11)另外我们还可以interrupt()方法来强制使线程恢复到运行状态中来,让线程具有cpu的执行资格,强制的动作会引发InterruptedException异常。