------- android培训、java培训、期待与您交流! ----------
day11 多线程
1、进程:正在执行的程序。
线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)。
进程中至少有一个线程。
2、对于JVM启动时,至少有两个线程:jvm的主线程,jvm的垃圾回收线程。
3、创建线程的第一种方式:继承Thread类。 参见ThreadDemo.java
步骤:1,定义类继承Thread。
2,复写Thread类中的run方法。目的是将自定义代码存储在run方法,让线程运行。
3,调用线程的start方法,该方法有两个作用:启动线程,调用run方法。
(面试)start和run方法的区别
为什么要覆盖run方法呢?
Thread类用于描述线程。Thread类中的run方法,用于存储线程要运行的代码。
Demo d = new Demo();//创建好一个线程。
d.start();//开启线程并执行该线程的run方法。
//d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
4、多线程的一个特性:随机性。谁抢到谁执行,至于执行多长,cpu说的算。
5、线程都有自己默认的名称:Thread-编号 该编号从0开始。
static Thread currentThread():获取当前线程对象。
getName(): 获取线程名称。 设置线程名称:setName或者构造函数。
6、线程的四种状态:被创建、运行、冻结、消亡。还有一种特殊的状态:临时状态。
临时状态的特点:具备了执行资格,但不具备执行权。
冻结状态的特点:放弃了执行资格。
7、创建线程的第二种方式:实现Runable接口 参见TicketDemo2.java
步骤:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法,将线程要运行的代码存放在该run方法中。
若是run方法中出现异常,只能处理,不能抛,因为父类没有处理异常机制。
3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口的子类对象传递给Thread的构造函数?
因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去执行指定对象的run方法,就必须明确该run方法所属对象。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
8、实现方式(Runnable接口)和继承方式(Thread类)有什么区别呢?
实现方式好处:避免了单继承的局限性。 在定义线程时,建议使用实现方式。
两种方式区别:
继承Thread:线程代码存放在Thread子类的run方法中。
实现Runnable:线程代码存放在实现了接口的子类的run方法中。
9、多线程运行期间会出现安全问题的原因在于: 参见TicketDemo2.java
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。
1,多个线程访问出现延迟;
2,线程的随机性。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
10、Java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。
synchronized(对象) { 需要被同步的代码 }
对象如同锁一样,持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取到锁。
11、同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
未满足这两个条件,不能称之为同步。
必须保证在同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
12、如何找问题: 参见BankDemo.java
1,明确哪些代码是多线程运行代码。
2,明确共享数据。
3,明确多线程运行代码中哪些语句是操作共享数据的。
13、同步函数(在函数上加上synchronized修饰符)用的是哪一个锁呢?
参见 ThisLockDemo.java
函数需要被对象调用,所以同步函数使用的锁是this。
Object obj = new Object(); 有些时候obj也可以作为锁使用。
14、同步函数被静态修饰后,使用的锁是该方法所在类的字节码文件对象,类名.class。
15、单例设计模式:(面试问题) 参见SingleDemo.java
问懒汉式和饿汉式有什么不同?
懒汉式的特点在于实例的延时加载。
问懒汉式延时加载有没有问题?
有,如果多线程访问时会出现安全问题。
怎么解决?
可以加同步来解决。而加同步的方式用同步代码块和同步函数都行,但是稍微有些低效。用双重判断的形式可以解决效率问题。
问加同步的时候使用的锁是哪一个?
该类所属的字节码文件对象,即.class文件。
死锁:即同步中嵌套同步。 参见:DeadLockDemo.java和DeadLockTest.java