多线程的复习

来源:互联网 发布:怎样导出数据库 编辑:程序博客网 时间:2024/06/11 18:03


因为之前学过的缘故,一上午在图书馆学完了多线程的内容,对线程有了更深入的理解。


CPU等硬件资源并不受应用程序控制,而是受操作系统控制,由操作系统来进行分配与调用。
并且多线程操作时一定要注意死锁、同步、通信等问题,总的一个理解可以说是逻辑问题,必须让程序以符合逻辑的形式运行。
同时在处理这些问题时,面对对象的编程理念会简化这种逻辑,使代码清晰明了,容易理解,也更加稳定、安全。
 
1.创建多线程可以使用继承Thread类和实现Runnable接口。在使用中,都是调用线程对象的run()方法。
   new Thread().start();这样的语句没有意义,因为Thread类中的run()方法什么也不做。
   在使用Thread(Runnable target)方法创建线程对象时,需为该方法传递一个实现了Runnable接口的类对象。
   new Thread()方法产生的线程每个都对应一个自己独立的空间,有独立的代码与数据。
   Runnable方法产生的线程可以共享代码与数据,对同一个对象进行多线程操作。
2.后台线程与联合线程。
对java程序来说,只要还有一个前台线程在运行,这个进程就不会结束,如果进程中只有后台线程在运行,这个进程就会结束。
如果在一个线程对象启动(调用start())前,调用setDaemon(true)方法,就可以使线程成为后台线程。
可以用join()方法来联合线程,join()也可以带参数,分别是join(long millis)和join(long millis,int nanos),用来指定在合并的时间后再分离。
3.多线程的应用。多线程有良好的交互性,分离性,可以灵活运用。
4.线程同步。多线程操作时,由于程序本身并不控制CPU资源的分配,极易引起错误的操作,造成数据的不一致性等等。所以有必要让多线程同步操作,也就是同一时间只能有一个线程执行特定的操作,这就是线程同步。
用synchronized(object){代码段}来定义一个监视器,所以与该监视器同步的线程只能有一个在一定时间执行同步代码块内的操作。
每个对象都有一个标志位,称为锁旗标。
函数的同步只要在定义函数前加上synchronized关键字即可。代码块与函数的同步可以用“ this ”对象,也就是函数所在的对象。
5.死锁问题,可以说是一种逻辑错误。线程的通信可以使用某一同步标志对象的wait()、notify()、notifyAll()来实现。
6.线程的生命控制。一定要明白线程的生命周期,并不是调用start()以后就直接运行了,而是进入了Runnable状态,等待系统调度器来分配资源,然后才能运行,并可能被暂时打断,运行其他的线程。另外还有同步、通信等影响。要注意理解。
线程生命的控制可以用标志成员变量和方法调用来实现。
 
附练习代码:
class ThreadDemo1
{
 public static void main(String [] args)
 {
  //new TestThread().start();    //run();该start()方法自动调用自己函数中的run()方法
  /*Thread tt = new TestThread();
  //tt.setDaemon(true);  设置为后台线程
  tt.start();*/
/*  Thread tt  = new Thread(new TestThread());
  tt.start();
  int index = 0;
  while(true)
  {
   if(index++==1000)
   try{tt.join(10000);}catch(Exception e){}  //join方法用来合并线程,必须对其进行异常处理
   System.out.println("main(): "+Thread.currentThread().getName());
  }*/
/*  new TestThread().start();
  new TestThread().start();
  new TestThread().start();
  new TestThread().start();*/
  TestThread tt = new TestThread();
  new Thread(tt).start();   //注意该句只是启动一个线程,可能还没有运行代码,cpu就切换到其他语句运行了!!!
  try{Thread.sleep(1);}catch(Exception e){}
  tt.str = new String("method");  //!!!注意此处str是对象类型的,所以要以一个新对象或对象引用变量的方式对其赋值
  new Thread(tt).start();
  new Thread(tt).start();
  new Thread(tt).start();
 }
}
class TestThread implements Runnable //extends Thread  //使用Runnable接口
{
  int tickets=100;
  String str = new String("");  //!!!!!注意作为同步标志对象的声明位置
  boolean sale = true;
 public void run()
 {
  if(str.equals("method"))
  {
    while(true)
     {
      synchronized(str)  //看来Object类中应该声明了一个成员变量,来作为对象的锁旗标
      //synchronized(this) //函数与代码块的同步使用this来同步,注意理解同步标志对象必须是同一个对象的概念
      {
       if(tickets >0)
       {
        try{Thread.sleep(10);}catch(Exception e){}
        //System.out.println("run(): "+Thread.currentThread().getName());
        //synchronized(this){} 造成死锁
        System.out.println(Thread.currentThread().getName()+" is saling ticket" + tickets--);
       }
        else 
        {
         sale=false;
         break;
        }
      }
     }
   }
  else
   {
    while(sale)
    {
     sale();
    }
   }
  System.out.println(Thread.currentThread().getName()+" is ending"); 
  System.out.println("Tickets="+tickets);  //打印出几行Tickets=0,!!体会多线程的运行过程
 }
 public synchronized void sale()
 {
    if(tickets >0)
    {
     try{Thread.sleep(10);}catch(Exception e){}
     //synchronized(str){}   造成死锁
     System.out.print("sale():");
     System.out.println(Thread.currentThread().getName()+" is saling ticket" + tickets--);
    }
    else
     sale=false;
 }
}
 
class Producer implements Runnable
{
 Q q;
 public Producer(Q q)
 {
  this.q=q;
 }
 public Producer(){}
 int i=0;
 public void run()
 {
   while(true)
   {
    /*synchronized(q)
    {
      if(q.full)
      {
       try 
       {
        q.wait();
       }
       catch(Exception e)
       {}
      }
      if (i==0)
      {
       q.name = "张三";
       try{Thread.sleep(1);}catch(Exception e){}
       q.sex ="男";
      }
      else
      {
       q.name = "李四";
       q.sex = "女";
      }
     
      System.out.println("i="+i);
      i=(i+1)%2;
      q.full=true;
      q.notify();
     
    }*/
    
    if(i==0) q.put("张三","男");
    else  q.put("李四","女");
    System.out.println("i="+i);
    i=(i+1)%2;
    
  }
 }
}
class Consumer implements Runnable
{
 Q q;
 public Consumer(Q q)
 {
  this.q=q;
 }
 public Consumer(){}
 public void run()
 {
  while(true)
  {
   /*synchronized(q)
   {
     if(!q.full)
     {
      try 
      {
       q.wait();
      }
      catch(Exception e)
      {}
     }
    try{Thread.sleep(1);}catch(Exception e){}
    System.out.println(q.name+"  "+q.sex);
    q.full=false;
    q.notify();  
   }*/
  q.get();
  }
  
 }
}
class Q      //注意体会面向对象的思想,强内聚,弱耦合
{
 private String name = "unknown";
 private String sex = "unknown";
 private boolean full=false;
 public synchronized void put(String name,String sex)
 {
 if(full) try{wait();}catch(Exception e){}
  this.name=name;
  this.sex=sex;
  full=true;
  notify();
 }
 public synchronized void get()
 {
  if(!full) {try{wait();}catch(Exception e){}}
  System.out.println(name+ " "+sex);
  full=false;
  notify();
 }
}
class TestThCom
{
 public static void main(String args[])
 {
  Q q = new Q();
  Producer pro = new Producer(q);
  Consumer con = new Consumer(q);
  new Thread(pro).start();
  new Thread(con).start();
  
 }
}
 
class TestThread implements Runnable
{
 private boolean bstop = false;
 public void run()
 {
  int i=1;
  while(!bstop)
  {
   System.out.println(Thread.currentThread().getName()+" is running "+i+" times");
   i++;
  }
  
 }
 public void stopMe()
 {
  bstop = true;
 }
}
class ThreadLife
{
 public static void main(String []args)
 {
  TestThread t1 = new TestThread();
  TestThread t2 = new TestThread();
  new Thread(t1).start();
  new Thread(t2).start();
  for(int i=0;i<100;i++)
  {
   if(i==50) 
   {
    t1.stopMe();
    t2.stopMe();
   }
   System.out.println("main() is running"+i+" times");
  }
 }
}
0 0