JAVA线程之七:线程的生命周期及死锁

来源:互联网 发布:户型图制作软件 编辑:程序博客网 时间:2024/05/29 07:08

一,线程的四个主要周期状态是“创建”,“可执行”,“非可执行”,“消亡”,状态转换关系如下图:

(1)创建。当实例化一个thread对象并执行start()方法后,线程进入“可执行”状态开始执行。虽然多线程给用户一种同时执行的假象,但事实上在同一时间点内,只有一个线程在执行,只是线程之间切换的动作非常快,所以看起来跟同时执行一样。

(2)可执行。当线程启用start()方法之后,进入“可执行”状态,执行用户覆写的run方法。当一个线程进入“可执行”状态下,并不代表它可以一直执行到run()结束。因为事实上它只是加入此应用程序执行安排的队列中,正在等待分享CPU资源,也就是等候执行权,在何时给予线程执行权,则由JAVA虚拟机决定,同时也由线程的优先级决定。

(3)非可执行。在“可执行”状态下,线程可能执行完毕;也可能没有执行完毕,处于等待执行权的队列中,此时线程进入“非可执行”状态。可以使用thread类中的wait(),sleep()方法使线程进入“非可执行”状态。

      当线程进入“非可执行”态,CPU就不分配时间片给这个线程。若希望线程回到“可执行”状态下,可以使用notify()方法、notifyAll()方法以及interrupt()方法。

(4)消亡。当run方法执行完毕后,线程自动消亡,也就是run()执行完毕后,该thread会自动终止。

二,关于多线程产生死锁

      因为线程可以阻塞,并且有同步控制机制可以防止其他线程在锁还没有释放的情况下访问这个对象,这时就产生了矛盾。比如:线程A在等待线程B,线程B又在等待线程A。这样就造成了死锁。

      造成死锁必须同时满足的4个条件:

(1)互斥条件。线程使用的资源必须至少有一个是不能共享的。

(2)请求与保持条件。至少有一个线程必须持有一个资源并且正在等待获取一个当前被其他线程持有的资源。

(3)非剥夺条件。分配的资源不能从相应的线程中被强制剥夺。

(4)循环等待。第一个线程等待其他线程,后者又在等待第一个线程。

     这四个条件同时满足时,才会导致死锁。所以要防止死锁的话,只需呀破坏其中一个条件即可。

 三,如果要求编写一个JAVA程序,模拟线程死锁,如下:

public class sss implements Runnable 

{
      private Object o1 = new Object();
      private Object o2 = new Object();
      public int value = 0; // 起一个标志作用
 
      public static void main(String[] args) throws InterruptedException

      {
             sss t1 = new sss();
             t1.value = 0;
             new Thread(t1).start();
  // 让当前线程睡眠
             Thread.sleep(500);
  // 修改value的值
             t1.value = 1;
             new Thread(t1).start();
        }
        public void run()

        {
              if (value == 0)

              {
                     synchronized (o1)

                     {
                            System.out.println("线程A : 我得到了o1的锁");
                            try

                            {
                                  // 让当前线程睡眠,从而让另外一个线程可以先得到对象o2的锁
                                   Thread.sleep(1000);
                             } catch (InterruptedException e)

                             {
                                    e.printStackTrace();
                              }
                              System.out.println("线程A : 我还想要得到o2的锁");
                             // 在得到o1锁之后,又想得到o2的锁
                             synchronized (o2)

                             {
                                   System.out.println("线程A : 我得到了o2的锁");
                              }
                       }
                }

                else

                {
                       synchronized (o2)

                       {
                              System.out.println("线程B : 我得到了o2的锁");
                              try

                              {
                                  // 让当前线程睡眠,从而让另外一个线程可以先得到对象o1的锁
                                     Thread.sleep(1000);
                               } catch (InterruptedException e)

                               {
                                       e.printStackTrace();
                               }
                               System.out.println("线程B : 我还想要得到o1的锁");
                            // 在得到o2锁之后,又想得到o1的锁
                               synchronized (o1)

                               {
                                      System.out.println("线程B : 我得到了o1的锁");
                                }
                          }
                  }
          }
}

执行结果:

线程A : 我得到了o1的锁
线程B : 我得到了o2的锁
线程A : 我还想要得到o2的锁
线程B : 我还想要得到o1的锁
参考原文:http://writeblog.csdn.net/PostEdit.aspx?entryId=5503392

原创粉丝点击