Java基础知识之我的理解---线程再回首
提纲:
一.开篇废话
二.再看多线程
???? 1)线程的状态(这一部分是总结前面所学的线程基础知识)
?????2)线程的同步问题(这一部分是最近的一些收获)
一.开篇废话???? Where又回来了,貌似有快一个学期没写技术博客了,虽然期间做过一些总结但也没发上博客,又到了假期可以安下心好好写点东西了,废话不多说,希望自己在寒假能安心下来好好学点东西,写点东西,那么让我们从线程开始。
二.再看线程
??? 1.线程的几个状态
???? 一个线程可以有四种状态:
???? (1) 新(New):线程对象已经创建,但尚未启动,所以不可运行。
?????????? 问题一:如何新建线程?
?????????? 答:让一个类成为线程类的方式有两种:一个是实现java.lang.Runnable接口,另一个是继承java.lang.Thread类。
?????????? 范例代码如下:
?????????? 运行结果:
??????????? -X-卖掉第 : 9 张
??????????? -X-卖掉第 : 8 张
??????????? -X-卖掉第 : 7 张
????????????-Y-卖掉第 : 10 张
??????????? -Y-卖掉第 : 5 张
??????????? -X-卖掉第 : 6 张
??????????? -Y-卖掉第 : 4 张
??????????? -X-卖掉第 : 3 张
??????????? -Y-卖掉第 : 2 张
??????????? -X-卖掉第 : 1 张??? 可已看出用这种方式的结果是对的,那么我们再来看看另一种。
????????? ?运行结果(这只是结果的一种情况):
???????? -Y-卖掉第 : 10 张
?????? ? -X-卖掉第 : 10 张
??????? ?-Y-卖掉第 : 9 张
???????? -Y-卖掉第 : 7 张
???????? -X-卖掉第 : 8 张
???????? -Y-卖掉第 : 6 张
??????? ?-Y-卖掉第 : 4 张
???????? ?-X-卖掉第 : 5 张
??????? ?- X-卖掉第 : 2 张
???????? ?-X-卖掉第 : 1 张
????????? -Y-卖掉第 : 3 张????????? 这次就有问题了,Y售票站已经将10号票售出为什么X又买出了一张10号票,这就是上面我们讲的那个问题。貌似到这里你该明白第三点了吧。
???? (2) 可运行(Runnable ):意味着一旦时间分片机制有空闲的CPU 周期提供给一个线程,那个线程便可立即
????????? 开始运行。因此,线程可能在、也可能不在运行当中,但一旦条件许可,没有什么能阻止它的运行——它既
????????? 没有“死”掉,也未被“堵塞”。
???? (3) 死(Dead):从自己的run()方法中返回后,一个线程便已“死”掉。亦可调用stop()令其死掉,但会
????????? 产生一个违例——属于Error 的一个子类(也就是说,我们通常不捕获它)。记住一个违例的“掷”出应当
????????? 是一个特殊事件,而不是正常程序运行的一部分。所以不建议你使用stop()(在Java 1.2 则是坚决反
??????????对)。另外还有一个destroy()方法(它永远不会实现),应该尽可能地避免调用它,因为它非常武断,根
????????? 本不会解除对象的锁定。
???? (4) 堵塞(Blocked):线程可以运行,但有某种东西阻碍了它。若线程处于堵塞状态,调度机制可以简单地
?????????? 跳过它,不给它分配任何CPU 时间。除非线程再次进入“可运行”状态,否则不会采取任何操作。??????? ?问题三:为何会堵塞?
???????? 答:堵塞状态是前述四种状态中最有趣的,值得我们作进一步的探讨。线程被堵塞可能是由下述五方面的原因造成的:
??????? 1.调用sleep(毫秒数),使线程进入“睡眠”状态。在规定的时间内,这个线程是不会运行的。
??????? 2. 用suspend()暂停了线程的执行。除非线程收到resume()消息,否则不会返回“可运行”状态。
??????? 3. 用wait()暂停了线程的执行。除非线程收到nofify()或者notifyAll()消息,否则不会变成“可运行”
?????????? (是的,这看起来同原因2 非常相象,但有一个明显的区别是我们马上要揭示的)。
??????? 4. 线程正在等候一些IO(输入输出)操作完成。
??????? 5. 线程试图调用另一个对象的“同步”方法,但那个对象处于锁定状态,暂时无法使用。??? 2.线程的同步问题(这一部分是最近的一些收获)
?????? 多线程一旦操作同一内存的数据就容易造成数据的混乱,也就是常说的线程安全问题。针对这个问题我们一般有四种解决方式:
采用synchronized关键字锁定要同步的方法采用synchronized关键字锁定要同步的代码块采用lock锁对象锁定同步代码,注意这里的所对象必须要为同一个否则加锁没意义。采用共享的代码操作为原子操作?在这一部分我用生产者消费者模型为例说明:场景模拟:有一个最大存货量为5的仓库,生产者往里放,消费者取,当放满了则生产者wait,当取空了则消费者wait.package 生产消费者模型;public class Test {/** * 测试入口 */public static void main(String[] args) {Store s = new Store(0);Thread pro1 = new Producer(s);Thread pro2 = new Producer(s);//Thread pro3 = new Producer(s);Thread cus1 = new Customer(s);Thread cus2 = new Customer(s);Thread cus3 = new Customer(s);pro1.start();pro2.start();//pro3.start();cus1.start();cus2.start();cus3.start();}}?运行结果(由于是while(true)所以只选取了部分结果来说明问题):??????? Thread-0当前仓库放入了1个或物
??????? Thread-2仓库被取走货物后剩下的货物为:0个
??????? Thread-3当前仓库已没有货物要取需等待
?????? ?Thread-1当前仓库放入了1个或物
????????Thread-3仓库被取走货物后剩下的货物为:0个
??????? Thread-4当前仓库已没有货物要取需等待
????????Thread-0当前仓库放入了1个或物
????????Thread-4仓库被取走货物后剩下的货物为:0个
??????? Thread-1当前仓库放入了1个或物
??????? Thread-0当前仓库放入了2个或物
??????? Thread-1当前仓库放入了3个或物
??????? Thread-0当前仓库放入了4个或物
??????? Thread-2仓库被取走货物后剩下的货物为:3个
??????? Thread-3仓库被取走货物后剩下的货物为:2个
??????? Thread-1当前仓库放入了3个或物
??????? Thread-0当前仓库放入了4个或物
??????? Thread-4仓库被取走货物后剩下的货物为:3个
????????Thread-1当前仓库放入了4个或物
??????? Thread-0当前仓库放入了5个或物
??????? Thread-1当前仓库已经存放到最大限度,需等待才能在放
??????? Thread-0当前仓库已经存放到最大限度,需等待才能在放
?????? Thread-2仓库被取走货物后剩下的货物为:4个
?????? Thread-1当前仓库放入了5个或物
?????? Thread-0当前仓库已经存放到最大限度,需等待才能在放
?????? Thread-3仓库被取走货物后剩下的货物为:4个
?????? Thread-0当前仓库放入了5个或物
?????? ...?????? 结果分析:
?????? (1)线程并不是按它们创建时的顺序运行的
????(2)当执行到后面,有多个wait(),那么notify该激活哪个wait或者说它有什么调度机制?根据结果(标红的部分)我们可以做此大胆猜想:这里有一个wait队列,先进先出,即notify相应最先进队列的wait.
????????
?
?