阻塞之后返回到就绪状态等待,还是有可能抢夺到下一次的执行权
Tread形参里面写入一个实现接口的实现类,就会执行实现类里的方法;
Runnable的run方法会运行在子线程之中的原因:
start会启动run方法,run方法会执行在子线程当中;
(target==null 就返回,否则调用target.run)
意思就是会执行target里的方法当做run方法;因为形参指向target了;
二,谁代表了了一个真正的线程
Runnable子类对象不代表一个线程,顶多算一个任务;
真正运行的是thread及子类对象(真正的线程是Tread的及其子类的对象,T T1= new T(实现接口对象))
Runnable的方式把代码和代码在哪条执行路径上运行区分开了,即把线程与执行
任务分开了;(因为如果是继承,就是继承类的对象来调用方法,而接口方式,是将实现类传给Tread来执行,也就是线程与任务之间是分开的)
多线程的安全问题:
多线程的运行环境(无法改变)
多线程共享数据(无法改变)
存在非原子操作(加锁)
什么是原子操作?一个操作要么完成要么不完成
解决多线程的安全问题:
思路:把产生多线程数据安全问题的原因破坏
同步:你走我不走(同步代码);异步:你走你的我走我的(多线程类似)
synchronized
synchronized同步代码块
synchronizde(){}:锁的对象可以是任意对象,但是要保证是同一个对象;
synchronized 方法,对象是this
静态synchronize方法的锁对象是字节码文件对象Class
总结:路过锁对象,把标志位改成加锁;退出同步代码块,标志为未上锁;
Lock
锁:在共享对象的上下lock.lock()和lock.unlock();一般用在try finally中
---
建议使用synchronized;
--
死锁:两个或以上的线程互相争抢资源而造成的互相等待的现象;
相互需要对方释放资源
两个线程进入之后,A线程拿到A锁,快速的线程切换中B线程拿到B锁,之后A等待B释放锁,B也是;所以相互等待,死锁了;
解决死锁,(一)考虑锁的顺序(二)将整个方法同步化
一个锁一个对象 共同使用;
-----------------------
wait方法
就是说:必须要在synchronized内使用,并且会释放监视器的所有权,直到被唤醒;
唤醒条件:要在相同对象的其他线程上才能唤醒 (该线程必须拥有该监视器)
----------
成员变量Random(成员对象,每次在run方法里面调用其方法得到随机的index)
foods[index]
--
为什么wait notify方法在obj中不在Thread:
因为在java中任意对象都可以充当锁对象(w,n两个方法都必须在拥有锁对象的类的同步方法之中,而锁对象不仅仅是线程对象)