创建线程:
 通过对java.lang包的查找,继承Thread类可以创建线程
  1,建立类继承Thread类
 2,复写Thread中的ran方法。
 3,调用线程的start()方法,该方法的作用是,启动线程,调用ran方法。
   public class Test {
 public static void main(String args[])
 {
 Demo a= new Demo();
 a.start();
 for(int x=0;x<=100;x++)
 System.out.println("hello word");
 }
  }
 class Demo extends Thread
 {
 public void ran()
 {
 for(int x=0;x<=100;x++)
 System.out.println("Demo ran");
 }
 }
   两个输出会交替出现。
 发现运行结果每次都不同
 因为多个线程都在获取cpu的使用权,cpu执行到谁,谁就运行,在某一时刻,只能有一个程序在运行(多核除外)cpu在做着快速切换,已达到看上去是在同时运行。
  多线程特性:随机性,谁抢到谁执行,至于执行多长时间,cpu说的算。
  为什么要覆盖ran方法
 thread类用于描述线程。
 该类定义了用于存储要运行的代码,这些代码就存储在ran方法中。
  ran() 和 start() 区别
  只写ran()线程没有被创建,编程了单线程程序。会顺序执行,输出不是随机的。
  线程运行过程中的状态:
      线程对象的名称:
 每个线程都有默认名称。
 Thread-编号   //该编号从0开始
 线程名称可以提供 线程.getName()  方法获得
  currentThread() :获取当前运行的线程对象
 getName():获取线程名称
    买票程序举例:
  public class Test
 {
 public static void main(String args [])
 {
 Ticket t1 = new Ticket();
 Ticket t2 = new Ticket();
 Ticket t3 = new Ticket();
 Ticket t4 = new Ticket();
 Ticket t5 = new Ticket();
  t1.start();
 t2.start();
 t3.start();
 t4.start();
 t5.start();
  }
 }
   class Ticket extends Thread
 {
 private static int tick=100; //静态,所有对象公用一个票数。
 public void run()
 {
 if(tick>0)
 System.out.println(currentThread().getName()+"sale:"+tick--);
 }
 }
   第二种创建进程的方法
 实现runable接口
  步骤:
 1,定义类,实现runnable接口
 2,覆盖runnable中的run()方法
 3,通过Thread;类建立线程对象
 4,将Runnable接口对象作为实际参数传递给Thread类的构造函数
 5,调用Thread类的start方法开启线程并调用Runnable子类中的run方法
  实现方式和前一种方法的区别:
 实现方式好处在于:避免了单继承的局限性。
 在定义线程时,建议使用实现方式。
 继承Thread类:线程代码存放在Thread子类对象run方法中
 实现Runnable:线程代码存放在接口的子类对象的run中
  在此例中ticket也不用static了,因为只建立了一个对象
 睡眠:
 try
 {Thread.sleep(10);}
 catch(Exception e)
 {
  }
 public class Test
 {
 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 Ticket implements Runnable
 {
 private int tick = 100;
 public void run()
 {
 while(true)
 if(tick>0)
 {
 System.out.println("sale"+tick--);
 }
  }
 }
    安全问题:
 以下代码会打印  0,-1,-2号票
 产生问题原因:
 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,另一个线程1参与进来执行,导致共享数据出现错误。 
  解决办法:对多条操作共享数据的语句,只能让让一个线程都执行完,在执行过程中,其他线程不可以参与执行。 
  java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。会保证该代码块内的代码被全部执行再切换线程。
 格式:
 synchronized(对象)
 {
 需要被同步的代码
 }
      public class Test
 {
 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 Ticket implements Runnable
 {
 private int tick = 100;
 public void run()
 {
 while(true)
 if(tick>0)
 {
 try
 {Thread.sleep(10);}
 catch(Exception e)
 {
  }
 System.out.println("sale"+tick--);
 }
  }
 }
  修改安全问题后的代码
     public class Test
 {
 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 Ticket implements Runnable
 {
 Object obj= new Object();
 private int tick = 100;
 public void run()
 {
 while(true)
 {
 synchronized(obj)
 {
 if(tick>0)
 {
 try
 {Thread.sleep(10);}
 catch(Exception e)
 {
  }
 System.out.println("sale"+tick--);
 }
 }
   }
 }
 }
   如何找到安全问题/同步的前提:
 1,明确哪些代码是多线程运行的代码。
 2,明确共享数据。
 3,明确多线程代码中哪些语句是操作共享数据的。
   同步函数:
 同步有两种,1代码块,2同步函数
 用synchronized修饰函数即可。
  同步代码块使用的锁时obj
  同步函数的锁:
 同步函数使用的所时this  也就是调用该函数的实体。
 如果同步函数被静态修饰后,使用的锁是该类对应的class,就是类名点class 。   Ticket.class
  懒汉式
       死锁:
 两个锁:
 同步中嵌套同步,锁却不同,恰好停止在某位置,会造成死锁。
 要避免死锁。
    public class Test
 {
 public static void main(String args [])
 {
 Thread t1 = new Thread(new Deadlock(true));
 Thread t2 = new Thread(new Deadlock(false));
 t1.start();
 t2.start();
 }
 }
  class Deadlock implements Runnable
 {
 private boolean flag;
  Deadlock(boolean flag)
 {
 this.flag = flag;
 }
 public void run()
 {
 if(flag)
 {
 while(true)
 {
 synchronized(Mylock.locka)
 {
 System.out.println("if lock a");
 synchronized(Mylock.lockb)
 {
 System.out.println("if lockb");
 }
 }
 }
 }
 else
 {
 while(true)
 {
 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();
 }