多线程
1.1进程
进程是一个正在运行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。
线程是进程中一个独立的控制单元,控制着进程的执行。
1.2如何在自定义的代码中,自定义一个线程?
API有一个对象Tread,创建一个线程,继承Tread类并重run方法。
其实,Thread类用来描述线程,该类就定义了一个线程,用于存储要执行的方法,该存储功能时run方法
1.3run与start调用的区别
run仅仅是对象调用方法,而线程创建了,但并没有运行。
start是开户线程并执行线程的run方法。
1.4线程运行状态
创建-运行:start方法
运行-冻结:sleep方法,wait方法
冻结-运行:notify方法
运行-消亡:stop方法,即run方法结束。
1.5方法
Thread currentThread();返回对当前正在执行的线程对象的引用。
String getName();返回该线程的名称。
setName(name);改变线程名称,使之与参数name相同。
new Thread(name);分配新的Thread对象。
1.6创建线程方法2
声明实现Runnable借口的类,该类然后实现run方法。
Thread t=new Thread(Runnable target,String name);
将实现Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
售票的例子就是应用了多线程。
1.7实现方式与继承方式有什么区别?
实现:避免了单继承的局限性。存储代码是实现接口Runnable的类run方法中。
继承:代码存放在继承了Thread类的run方法中。
1.8多线程的安全问题
多线程的安全问题原因是当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一线程参与进来执行,导致共享数据的错误。
解决办法:对多线程操作共享数据的语句,只能让一个线程执行完,其他线程不可以执行。
同步代码块:synchronized(对象)
{
需要被同步的代码;
}
同步函数:synchronized放在函数上,返回值前。
1.9 同步的前提:必须要有两个以上的线程,必须是多个线程使用同一个锁。
对象如同锁,持有锁的线程可以在同步中执行,没有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
如何找出多线程问题呢?】
1>明确哪些代码是多线程运行代码,1>明确共享数据,1>明确多线程运行代码中哪些语句是操作共享数据的。
分别将需要同步的,不需要的同步的代码通过封装将其分开。
1.10单例设计模式
其中有饿汉式,和懒汉式;懒汉式加上同步,效率会很低效,那么用双重判断来减少判断锁的次数。
1.11死锁
死锁即同步中嵌套同步,而锁却不同。
同步函数使用的锁是this,因为函数需要被对象调用,那么函数都有一个所属对象引用,那么就是this。
如果同步函数被静态修饰,使用的锁就不是this了,而是类名.class;使用的是该方法所在类的字节码文件对象。
1.12线程间的通信
线程间的通信是多个线程,在操作同一个资源,但操作的动作不同。
线程间的通信的安全问题解决方案:将锁换成了资源类对象。
等待唤醒机制:wait();notify();notifyAll();都使用在同步中,因为要对持有锁的线程操作,所以要使用在同步中,因为只有在同步中才有锁。
优化代码:即使将资源类私有化。
1.13消费者与生产者
多个线程生产,多个线程消费中的安全问题:可能出现生产一个商品,该商品消费了两次,也可能生产了两个商品,只有一个被消费者消费了等。
解决:首先定义while判断标记,然后使用notifyAll唤醒对方线程。
1.14停止线程
定义循环结束标记或者使用interrupt中断方法。
interrupt方法是结束线程的冻结状态,使线程恢复到运行状态。
注意,stop方法已经过时,不同了、
1.15守护线程
setDaemon();将该线程标记为守护线程或用户线程。
该方法必须在线程启动前调用。作用是随着前台线程结束而结束。
join方法:等待该线程终止,后面的线程才能执行。
toString方法:返回该线程的字符串表示形式,包括线程名称,优先级和线程组。
yeild方法:暂停当前正在运行的线程对象,并执行其他线程。