BloveSaga

在希腊帕尔纳斯山南坡上,有一个驰名世界的戴尔波伊神托所,在它的入口处的巨石上赫然锈刻着这样几个大字: 认识你自己!

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  34 随笔 :: 12 文章 :: 122 评论 :: 0 Trackbacks

         多线程学习

 * 程序,进程和线程
程序: 是指计算机指令的集合,它以文件的形式存储在磁盘上。
进程: 是一个程序在其自身的地址空间中的一次执行活动。

进程是资源的申请,调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请
系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不站用系统的运行资源。

线程: 是进程中一个单一的连接控制流程。一个进程可以有多个线程。

线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程
没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远
较进程简单。
 * Java对多线程的支持
Java在语言级提供了对多线程程序设计的支持。
实现线程程序的两种方式:
(1)从Thread类继承;
(2)实现Runnable接口。

Java运行时系统实现了一个用于调度线程执行的线程调度器,用于确定某一时刻由哪一个线程在
CPU上运行。
在java技术中,线程通常是抢占式的而不需要时间片分配进程(分配给每个线程相等的CPU时间的
进程)。抢占式调度模型就是许多线程处于可以运行状态(等待状态),但实际上只有一个线程在
运行。该线程一直运行到它终止进入可运行状态(等待状态),或者另一个具有更高优级的线程
变成可运行状态。在后一种情况下,低优先级的线程被高优先级的线程抢占,高优先级的线程获得
运行的机会。
Java线程调度器支持不同优先级线程的抢占方式,但其本身不支持相同优先级线程的时间片轮换。
Java运行时系统所在的操作系统(例如:windows2000)支持时间片的轮换,则线程调度器就支持
相同优先级线程的时间片轮换。

用多线程技术模拟一个售票系统
实现代码如下:
class TicketSystem
{
 public static void main(String[] args)
 {
  SellTicket st = new SellTicket();
  new Thread(st).start();
  new Thread(st).start();
  new Thread(st).start();
  new Thread(st).start();
 }
}
class SellTicket implements Runnable
{
 int tickets=100;
 Object o = new Object();
 public void run()
 {
  while(true)
  {
   /*
    synchronized(o)  //同步块在关键字后得加个对象(任意的对象都可以)
    {
      if(tickets>0)
     {
       try
      {
         Thread.sleep(10);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
          System.out.println(Thread.currentThread().getName()+
          "sell tickets"+tickets);
          tickets--;    
     }
    }
    */
    sell(); 
  }
 }
 public synchronized void sell()  //同步方法
 {
      if(tickets>0)
     {
       try
      {
         Thread.sleep(10);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
          System.out.println(Thread.currentThread().getName()+
          "sell tickets"+tickets);
          tickets--;    
     }   
 }
}
 * 线程的同步
 The code segments within a program that access the same object from separate,concurrent
 thread are called "critical sections"。
 同步的两种方式:同步块和同步方法
 没一个对象都有一个监视器(monitor),或者叫做琐。
 同步方法利用的是this所代表的对象的琐。
 每个class也有一个琐,是这个class所对应的Class对象的琐。
完整示例:
class TicketSystem
{
 public static void main(String[] args)
 {
  SellTicket st = new SellTicket();
  new Thread(st).start();
  /*
   *写一个try{}catch{}块让main()方法所在的线程睡1秒
   *主要是想要线程优先启动
  */
  try
  {
   Thread.sleep(1);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  st.b=true;
  new Thread(st).start();
  //new Thread(st).start();
  //new Thread(st).start();
 }
}
class SellTicket implements Runnable
{
 int tickets=100;
 Object obj = new Object();
 boolean b=false;
 public void run()
 {
  if(b==false)
  {
   while(true)
      sell();
  }
  else
  {
     while(true)
   {  
    synchronized(this)  //同步块在关键字后得加个对象(任意的对象都可以)
    {
      if(tickets>0)
     {
       try
      {
         Thread.sleep(10);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
          System.out.println("obj:"+Thread.currentThread().getName()+
          " sell tickets"+tickets);
          tickets--;    
     }
    }   
   // sell(); 
  }
  }

 }
 public synchronized void sell()  //同步方法
 {
      if(tickets>0)
     {
       try
      {
         Thread.sleep(10);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
          System.out.println("sell():"+Thread.currentThread().getName()+
          "sell tickets"+tickets);
          tickets--;    
     }   
 }
}

 * 线程的死琐
 哲学家进餐的问题
 一帮哲学家在一起进餐,但是每个人都只有1支筷子,大家都在等待别人拿出一支筷子让自己
 先吃,然后再把自己的拿出去,但是大家都不愿意拿出自己的筷子。
 线程1琐住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的
 监视器,就造成了死琐。

 示例代码:
class TicketSystem
{
 public static void main(String[] args)
 {
  SellTicket st = new SellTicket();
  new Thread(st).start();
  /*
   *写一个try{}catch{}块让main()方法所在的线程睡1秒
   *主要是想要线程优先启动
  */
  try
  {
   Thread.sleep(1);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  st.b=true;
  new Thread(st).start();
  //new Thread(st).start();
  //new Thread(st).start();
 }
}
class SellTicket implements Runnable
{
 int tickets=100;
 Object obj = new Object();
 boolean b=false;
 public void run()
 {
  if(b==false)
  {
   while(true)
      sell();
  }
  else
  {
     while(true)
   {  
    synchronized(obj)  //同步块在关键字后得加个对象(任意的对象都可以)
    {
       try
      {
         Thread.sleep(10);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      } 
      synchronized(this)
      {      
            if(tickets>0)
             {
                System.out.println("obj:"+Thread.currentThread().getName()+
                " sell tickets"+tickets);
                tickets--;    
              }
      }
      }   
    }
  }

 }
 public synchronized void sell()  //同步方法
 {
  synchronized(obj)
  {
      if(tickets>0)
     {
       try
      {
         Thread.sleep(10);
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
          System.out.println("sell():"+Thread.currentThread().getName()+
          "sell tickets"+tickets);
          tickets--;    
     }
  } 
 }
}
 * wait,notify,notifyAll
 每个对象除了有一个琐之外,还有一个等待队列(wait set),当一个对象刚刚创建的时候,它
 的等待队列是空的。
 我们应该在当前线程锁住对象的琐后,去调用该对象的wait方法。
 当调用对象的notify方法时,将从该对象的等待队列中删除一个任意的线程,这个线程将再次
 成为可运行的线程。
 当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将
 成为可运行的线程。
 wait和notify重要用于producer-consumer这种关系中。
 代码示例:
 class Test
{
 public static void main(String[] args)
 {
  Queque q = new Queque();
  Procedur p = new Procedur(q);
  Consumer c = new Consumer(q);
  p.start();
  c.start();
  
 }
}

class Procedur extends Thread   //生产者
{
 Queque q;
 Procedur(Queque q)
 {
  this.q=q;
 }
 public void run()
 {
  for(int i=0;i<10;i++)
  {
   q.put(i);
   System.out.println("Procedur put"+ i);
  }
 }
}

class Consumer extends Thread   //消费者
{
 Queque q;
 Consumer(Queque q)
 {
  this.q=q;
 }
 public void run()
 {
  while(true)
  {
   System.out.println("Consumer get"+q.get());
  }
 }
}

class Queque    //放置数据
{
 int value;
 boolean bFull=false;
 public synchronized void put(int i)
 {
  if(!bFull)
  {
    value=i; 
    bFull=true;
    notify();  
  }
  try
  {
   wait();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }
 public synchronized int get()
 {
  if(!bFull)
  {
   try
   {
    wait();
   }
   catch(Exception e)
   {
    e.printStackTrace();
   }
  }
  bFull=false;
  notify();
  return value;
 }
}


 线程的状态图

   |
   | new Thread
   |                   yield      sleep,wait,suspend,I/O阻塞
  \|/ start                     |------------------------------------>|
  New----->Runnable|                                                        |Not Runnable
                            \    |<------------------------------------|         /
                             \     sleep结束,notify,resume,I/O操作完成    /
                              \                                                                 /
                               \                                                              /
                                \                                                           /
                                 \                                                         /
                                  \ run方法退出                                /
                                   \stop方法调用                             /
                                    \                                                /
                                     \                                             / 
                                      \                                          /  stop方法调用
                                       \                                       /
                                        \                                     /
                                         \                                   /
                                          \                                /
                                           \                             /
                                            \                           /
                                             \ ______ _____/
                                              |      Dead         |
                                              |____________|
 线程的终止
 
 设置一个flag变量。
 结合interrupt()方法。
 code:
class TestThread
{
 public static void main(String[] args)
 {
  Thread1 t1=new Thread1();
  t1.start();
  int index=0;
  while(true)
  {
   if(index++==500)
   {
    t1.stopThread();
    break;
   }
   System.out.println(Thread.currentThread().getName());
  }
 }
}

class Thread1 extends Thread
{
 private boolean bStop=false;
 public void run()
 {
  while(!bStop)
  {
   System.out.println(getName());
  }
 }
 public void stopThread()
 {
  bStop=true;
 }
}

posted on 2006-06-08 12:21 蓝色Saga 阅读(147) 评论(0)  编辑  收藏 所属分类: Basic Study for JAVA

只有注册用户登录后才能发表评论。


网站导航: