黑马程序员_多线程与死锁

来源:互联网 发布:网络搞笑猛虎下山图 编辑:程序博客网 时间:2024/06/05 20:14

------- android培训、java培训、期待与您交流! ----------

 

一、线程的创建

1、继承Thread类

创建步骤:
1、定义类继承Thread
2、复写Thread类中的run方法
3、调用线程的start方法
此方法有两个作用:
启动线程
调用run()方法

class Demo extends Thread//定义类继承Thread{ public void run()//复写run()方法 { for(int x=0; x<60; x++) System.out.println("Demo run()---"+x); }}class ThreadDemo{ public static void main(String[] args) { Demo d = new Demo();//创建一个线程 d.start();//开启线程,并调用线程的run()方法

for(int x=0; x<60; x++) System.out.println("Hello Thread!---"+x); }}

程序运行结果如下:
黑马程序员_多线程 - freedomheaven - freedomheaven的博客
 运行结果每一次都不同。
因为多个下次都要获取CPU的执行权,CPU执行到谁,谁就运行。
但是在某一时刻,只能有一个程序在运行。(多核除外)
多线程的一个特性,随机性。

2、实现Runnable接口

/*需求:简单的卖票程序,多个窗口同是卖票。

创建线程的第二种方式:实现Runnable接口

步骤:1、定义类实现Runnable接口2、覆盖Runnable接口中的run方法。 将线程要运行的代码存放在该run方法中。3、通过Thread类建立线程对象。4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。5、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

*/class Ticket implements Runnable{ private int tick = 100; public void run() { while (true) { if(tick>0) { System.out.println(Thread.currentThread().getName()+"---sale : "+tick--); } } }}class TicketDemo{ public static void main(String[] args) { Ticket t = new Ticket();

Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); }}

程序运行结果如下:
黑马程序员_多线程 - freedomheaven - freedomheaven的博客

3、两种方法对比


实现方式和继承方式有什么区别?

实现方式好处:避免了单继承的局限性。
在定义线程时,建议使用实现方式。

两种方式区别:
继承Thread:线程代码存放在Thread子类run方法中。
实现Runnable:线程代码存放在接口的子类的run方法中。

二、多线程的安全问题

1、通过分析上述程序,发现存在安全隐患,可以通过代码进行验证。

class Ticket implements Runnable { private int tick = 100; public synchronized void run() { while (true) { if(tick>0) { //因为继承了接口,而接口中没有异常的抛出,所以只能try try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"---sale : "+tick--); } } }}

修改后运行结果出现以下情况:
黑马程序员_多线程 - freedomheaven - freedomheaven的博客
出现问题原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还未执行完,另一个线程就进入执行,从而导致共享数据出错。
2、JAVA对多线程安全问题有专业解决方式:同步代码块。synchronized(对象){ 需要被同步的代码}

具体代码如下:

 

class Ticket implements Runnable { //Object obj = new Object();  private int tick = 1000; public void run()  {  while (true)  {   synchronized(this)   {    if(tick>0)    {     //因为继承了接口,而接口中没有异常的抛出,所以只能try     try{Thread.sleep(10);}catch(Exception e){}     System.out.println(Thread.currentThread().getName()+"---sale  : "+tick--);    }   }  } }}class TicketDemo2{ public static void main(String[] args)  {  Ticket t = new Ticket();

 

  Thread t1 = new Thread(t);  Thread t2 = new Thread(t);  Thread t3 = new Thread(t);  Thread t4 = new Thread(t);  Thread t5 = new Thread(t);    t1.start();  t2.start();  t3.start();  t4.start();  t5.start();   }}

代码修改后,运行结果中未出现为0等错误情况。

好像是CPU的缘故,在票数1000的时候,只能看到一个线程。当票数为10000的时候,方可看到其他线程运行的情况。

 

3、单例设计模式

 

/*单例设计模式

 

*///饿汗式class Single{ private static final Single s = new Single(); private Single(){} public static Single getInstance() {  return s; }}

 

//懒汉式

//延迟加载单例模式class Single{ private static Single s = null; private Single(){} public static Single getInstance() {  synchronized(Single.class)//通过锁确保程序在多线程访问时运行安全  {   if(s==null)    s = new Single();  }  return s; }}

 

发现懒汉式中,如果有一个线程进入锁中,其它线程只能等待,会导致程序效率低,继续对其进行完善。

class Single{ private static Single s = null; private Single(){} public static Single getInstance() {  if(s==null)//进行判断,如果不为空,就不需要等待锁。  {   synchronized(Single.class)   {    if(s==null)     s = new Single();   }  }  return s; }}

 

 

三、死锁的探讨
 

/*死锁形成探讨*/class Test implements Runnable{ private boolean flag; Test(boolean flag)//建立标识,让两个线程分别运行。 {  this.flag = flag; } public void run()//锁相互嵌套,形成各自占用资源,同时需要对方资源。 {  if (flag)  {   synchronized(MyLock.LockA)   {    System.out.println("if LockA");    synchronized(MyLock.LockB)    {     System.out.println("if LockB");    }   }  }  else  {   synchronized(MyLock.LockB)   {    System.out.println("else LockB");    synchronized(MyLock.LockA)    {     System.out.println("else LockA");    }   }  } }}class MyLock//创建两个锁{ static Object LockA = new Object(); static Object LockB = new Object();}class DeadLockDemo{ public static void main(String[] args) {  Thread t1 = new Thread(new Test(true));//创建线程t1  Thread t2 = new Thread(new Test(false));//创建线程t2

  t1.start();  t2.start(); }}

程序运行结果如下:
黑马程序员_多线程 - freedomheaven - freedomheaven的博客
可见:两个线程分别只运行了第一输出语句,便形成了死锁。
 

----------- android培训、java培训、期待与您交流! --------------   

详细请查看:http://edu.csdn.net/heima/

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小班走丢了怎么办反思 房屋外墙漏水物业不管怎么办 厨房墙砖用色花怎么办 小孩子做错事很偏激怎么办 孩子在学校偷钱怎么办 房间墙壁上到处有湿虫怎么办 买了西晒的房子怎么办 墙面瓷砖下水管漏水怎么办 西晒房间开空调没效果怎么办 墙纸被小孩画了怎么办 集成墙板缝隙大怎么办 高血压变低血压怎么办会恢复吗 总是感觉睡不够好困怎么办 两岁宝宝说有鬼怎么办 阳台改成了卧室晒衣服怎么办 室外墙角边墙泥受潮脱落怎么办 新房装修墙体发霉了怎么办 宝宝吃多了发烧怎么办 宝宝睡觉不爱盖被子怎么办 1岁宝宝不盖被子怎么办 2岁宝宝不盖被子怎么办 买的芬琳漆不够刷的怎么办 1.3米宽厨房门怎么办 墙面漆颜色刷深了怎么办 地板上沾了墙漆怎么办 孩子连发高烧8天了怎么办 孩子对数字不敏感怎么办 三岁宝宝不爱学习怎么办 5岁还不认识数字怎么办 小孩上中班还不认识数字怎么办 中班小孩数字都不认识怎么办 中班小孩记不住数字怎么办 中班小孩不肯练数字描红怎么办 2个月吃母乳婴儿缺钙怎么办 月经期接吻水多怎么办 4岁宝宝晚上尿多怎么办 2岁宝宝晚上尿多怎么办 3岁宝宝晚上尿多怎么办 宝宝拉肚子拉绿色的屎怎么办 婴儿吃奶粉大便干燥怎么办 母乳宝宝不拉大便怎么办