黑马程序员---java基础------------------多线程

  线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。

  线程的创建

    一:继承Thread类。步骤:

      1,定义类继承Thread。

      2,复写Thread类中的run方法。      目的:将自定义代码存储在run方法。让线程运行。

            class Demo extends Thread
            {
                 public void run()
                 {
                      for(int x=0; x<60; x++)
                           System.out.println("demo run----"+x);
                 }
            }

      3,调用线程的start方法,               该方法两个作用:启动线程,调用run方法。

            

            class ThreadDemo {  

                public static void main(String[] args)  {  

                     //for(int x=0; x<4000; x++)   

                    //System.out.println("Hello World!");

                     Demo d = new Demo();//创建好一个线程。   

                    //d.start();//开启线程并执行该线程的run方法。  

                    d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。

                       for(int x=0; x<60; x++)    

                        System.out.println("Hello World!--"+x);

                 }

             }

      线程的运行状态:

          

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

        步骤:

          1,定义类实现Runnable接口

          2,覆盖Runnable接口中的run方法。  将线程要运行的代码存放在该run方法中。

          3,通过Thread类建立线程对象。

          4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。

          5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

class Ticket implements Runnable//extends Thread {     

      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();

    }

}

      为什么要将Runnable接口的子类对象传递给Thread的构造函数?
         因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。

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

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

        继承Thread:线程代码存放Thread子类run方法中。

        实现Runnable,线程代码存在接口的子类的run方法。

      获取当前线程对象:static Thread currentThread();

      获取线程名称:getName();

 

class Test extends Thread {  

    Test(String name)  {   //父类有这样的构造方法

      super(name);  

    }  

    public void run()  {   

        for(int x=0; x<60; x++)   {    

          System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x);   

        }

     }

}

class ThreadTest
{
   public static void main(String[] args)
   {
      Test t1 = new Test("one---");
      Test t2 = new Test("two+++");
      t1.start();
      t2.start();

  }

}

    多线程的安全问题:通过分析,发现,打印出0,-1,-2等错票。问题的原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执

行完,另一个线程参与进来执行。导致共享数据的错误。解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。这就出来了

同步代码块

synchronized(对象) {  

    需要被同步的代码

}

    对象如同锁。持有锁的线程可以在同步中执行。 没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

    同步的前提:1,必须要有两个或者两个以上的线程;2,必须是多个线程使用同一个锁。    

    好处:解决了多线程的安全问题。

    弊端:多个线程需要判断锁,较为消耗资源。

class Ticket implements Runnable {

     private  int tick = 1000;  

    Object obj = new Object();  

    public void run()  {   

        while(true)   {    

          synchronized(obj)    {     

            if(tick>0)     {      

                //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);   

          t1.start();  

          t2.start();   

          t3.start();   

          t4.start();

      }

 }

      同步函数:同步代码块用来封装代码的,函数也是来封装代码的,我们试图让函数具备同步性,也可以达到相同的效果。   

class Bank {  

    private int sum;  

    public synchronized void add(int n)  {  

          sum = sum + n;   

          try{Thread.sleep(10);

         }catch(Exception e){}    

         System.out.println("sum="+sum);   

      }

}

class Cus implements Runnable {

      private Bank b = new Bank();  

      public void run()  {     

        for(int x=0; x<3; x++)   {

               b.add(100);   

        }

     }

}

class  BankDemo {  

    public static void main(String[] args)  {

        Cus c = new Cus();   

      Thread t1 = new Thread(c);   

      Thread t2 = new Thread(c);  

       t1.start();   

      t2.start();  

    }

}

    验证同步函数的锁对象是this:如果直接将synchronized关键字放到run() 函数上做成同步函数,发现效果不行 ,应为只启动了0号线程,分析后得知,是同步的代码没弄清楚,后来将同步代码部分提取后,封装成独立的show()函数调用并同步synchronized,就可以了。这个时候问一个问题,它的锁是什么呢?函数需要被对象调用,函数都有一个所属对象的引用时this所以同步函数的锁对象是this。为了验证,使用两个线程买票,一个线程在同步代码快中,一个在同步函数中,都在执行买票动作,如果要是同步就不会出现错误的票。

class Ticket implements Runnable {  

    private  int tick = 100;  

    //Object obj = new Object();  

    boolean flag = true;  

    public  void run()  {   

        if(flag)   {    

            while(true)    {     

                //synchronized(this)     {      

                    if(tick>0)      {      

                         try{Thread.sleep(10);}catch(Exception e){}       

                         System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);      

                    }     

                }   

             }   

         }   

          else    

            while(true)     

                show();  

    }

     public synchronized void show()//this  

    {   

        if(tick>0)   {   

           try{Thread.sleep(10);}catch(Exception e){}    

          System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);   

        }  

    }

}

class  ThisLockDemo {

     public static void main(String[] args)  {

          Ticket t = new Ticket();

          Thread t1 = new Thread(t);   

          Thread t2 = new Thread(t);   

          t1.start();   

          try{

            Thread.sleep(10);

         }catch(Exception e){}  

         t.flag = false;   

        t2.start();
     }
}

    函数被静态修饰后,使用的锁是:类名.class

 

class Ticket implements Runnable {  

    private static  int tick = 100;  

    //Object obj = new Object();

     boolean flag = true;  

    public  void run()  {   

      if(flag)   {   

           while(true)    {     

              synchronized(Ticket.class)     {     

                   if(tick>0)      {       

                      try{Thread.sleep(10);}catch(Exception e){}       

                      System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);     

                   }     

              }    

           }   

       }   

       else    

          while(true)     

              show();  

    }  

    public static synchronized void show()  {   

          if(tick>0)   {    

              try{Thread.sleep(10);}catch(Exception e){}    

              System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);   

          }  

    }

}

 

class  StaticMethodDemo {

     public static void main(String[] args)  {

          Ticket t = new Ticket();

          Thread t1 = new Thread(t);   

          Thread t2 = new Thread(t);  

          t1.start();   

          try{Thread.sleep(10);}catch(Exception e){}   

          t.flag = false;  

          t2.start();

     }

}

单例设计模式

懒汉式:

class Single {  

    private static Single s = null;  

    private Single(){}

     public static  Single getInstance()  {   

        if(s==null)   {    

            synchronized(Single.class)    {     

                if(s==null)      

                //--->A;      

                s = new Single();    

            }   

        }   

        return s;  

     }

}

class SingleDemo {  

    public static void main(String[] args)  {   

        System.out.println("Hello World!");  

    }

}

    死锁:

class Test implements Runnable {  

    private boolean flag;  

    Test(boolean flag)  {   

        this.flag = flag;  

    }

     public void run()  {   

        if(flag)   {    

            while(true)    {     

                synchronized(MyLock.locka)     {      

                      System.out.println(Thread.currentThread().getName()+"...if locka ");      

                      synchronized(MyLock.lockb)      {       

                          System.out.println(Thread.currentThread().getName()+"..if lockb");           

                      }     

                }    

            }   

        }   

        else   {    

            while(true)    {       

                synchronized(MyLock.lockb)     {      

                      System.out.println(Thread.currentThread().getName()+"..else lockb");      

                      synchronized(MyLock.locka)      {       

                          System.out.println(Thread.currentThread().getName()+".....else locka");      

                }     

            }    

        }   

    }  

  }

}

class MyLock {  

    static Object locka = new Object();  

    static Object lockb = new Object();

}

class  DeadLockTest {  

    public static void main(String[] args)  {   

        Thread t1 = new Thread(new Test(true));   

        Thread t2 = new Thread(new Test(false));   

        t1.start();   

        t2.start();  

    }

}

 

posted @ 2013-05-24 22:35  zhao198627  阅读(166)  评论(0编辑  收藏  举报