黑马程序员_java多线程总结

[亡魂溺海] 提交于 2020-03-12 05:16:55

android培训java培训、期待与您交流!


/*
 多线程技术
 java虚拟机允许程序并发地运行多个线程。
 JVM启动至少有两个线程,一个是主线程(代码在mian方法中);另一个是负责垃圾回收机制的线程。
 
 创建线程
 方法一
    在java.lang包中有一个Thread类
 继承Thread类
 步骤:
 1,定义类继承Thread.
 2,复写Threa类中的run方法;
  目的:将自定义代码存储在run方法中,让线程运行。
 3,调用start(),该方法有两个作用,就是启动线程,调用run方法。

*/
// 例:三个窗口分别买票,每一个窗口卖10张票

 class ThreadDemo extends Thread //定义类继承Thread.
 {
  
  public void run() //复习run方法
  { 
   int x=1;
   while(x<=10)
   {
    System.out.println(Thread.currentThread().getName()+"....."+x);//打印正在运行的线程
    x++;
   }
  }
 }
 class Test
 {
  public static void main(String[] String)
  {
   new ThreadDemo().start();//创建第一个线程并运行
   new ThreadDemo().start();//创建第二个线程并运行
   new ThreadDemo().start();//创建第三个线程并运行
  }
 }
 
 //要点:run方法用于存放线程要运行的代码。
/*
 方法二:通过实现Runable接口
 步骤:
 1,定义类实现(implements)Runnable接口;
 2,覆盖Runnable接口的run()方法
 3,通过Thread类建立线程对象。
 4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
 5,调用Thread类的start方法开启线程并调用Runnable的run方法。

 实现方式与继承方式的区别
 继承Thread:线程代码存放在Thread子类的run方法中。
 实现Runnable:线程代码存放在Runnable接口子类的run方法中。
 */

 //例如:购票小程序
 //有100张票三个窗口卖。三个窗口共享100张票。
 class ThreadDemo2 implements Runnable//定义类实现(implements)Runnable接口;
 {
  private int tick=10;
  public void run()//覆盖Runnable接口的run()方法
  {
   while(true)
   {
    if(tick>0)
    {
     //为了问题看起来明显一点在此睡上10毫秒,10好秒后自动回到可执行状态
     try{Thread.sleep(100);} catch(Exception e){}
     System.out.println(Thread.currentThread().getName()+"......."+tick--);
    }
    
   }
  }
 }
 class Test2
 {
  public static void main(String[] args)
  {
   ThreadDemo2 th=new ThreadDemo2();//创建ThreadDemo2对象,
   new Thread(th).start();//将th作为参数传递给Thread创建线程对象
   new Thread(th).start();//同上
   new Thread(th).start();//同上
  }
 }


 //以上程序是不安全的,存在线程安全性问题。此多线程操做的是共享数据,因为一个线程对多条语句只执行了一部分,还没完,这时另一个线程进来执行
 //导致共享数据错误。
 /*
 线程的周期
 一个线程有4种状态,任何一个线程肯定处于这4中状态中的一种。
 1,初始状态(New):当线程对象被建立之后,并在调用start()方法之前。此时线程处于初始状态。
    这时线程对象已经产生,但是没被启动。此时可调用start()启动线程和stop()方法停止线程。
 2,可执行状态(Runnable):当线程对象调用start方法后,线程就转入可执行状态。当有多个线程处于可执行状态时,
    这些线程都一个线程池中,排程器会按照先后顺序排列它们,当有CPU资源时,排程器会依次启动这些线程。
    所以,处于可执行状态的线程可能在它正在执行,也可能在线程池中等待。
 3,阻塞状态(NonRunnable):如线程对象调用wait()方法后,线程就处于阻塞状态。
    此时排程器会忽略它,不对它进行排程。由阻塞状态可以通过resume()方法恢复多可执行状态,它有可能重新执行。
 4,退出状态(Done):当一个线程正常结束或调用stop()方法。这个线程就退出了。

 控制线程周期的方法
 strat()  开启一个线程,由New状态Runnable状态
 stop()  结束一个线程,由初始状态或可执行状态转入Done状态。
 sleep(long) 线程暂停一段时间。由Runnable状态转入NonRunnable状态,时间到自动返回可执行状态。
 wait() 停止正在运行的线程,由Runnable状态转入NonRunnable状态。需要notify()唤醒。
 notify();唤醒由wait()停止的线程。
 notifyAll() 唤醒所有等待的线程。
 suspend() 挂起执行,由Runnable状态转入NonRunnable状态。
 resume() 恢复执行,由NonRunnable状态转入Runnable状态。
 yield() 明确放弃执行。线程由Runnable状态转入Runnable状态。

 
 多线程的安全性问题
 当多线程在操作共享数据是,就会出现安全性问题。因为一个线程对多条语句只执行了一部分,还没完,这时另一个线程进来执行
 导致共享数据错误。

 解决办法就是:同步代码块。
 同步代码块原理:当多线程操作共享数据时,一个线程执行完,才让另一个线程进来执行。
 格式:
 synchronized(对象)  此对象可以是任意的
 {
  需要被执行的代码(被多线程操作的共享数据)
 }
 
 同步代码块中对象如同锁,就是当一个线程执行到操作同步代码时,就把它锁住,不让其他的线程进入执行。
 当此线程执行操作完时,就释放锁。这时其他的线程才可以继续执行同步代码。
 
 同步的前提:
 1,必须有两个以上的线程
 3,多线程必须使用同一个锁
 
 同步的好处:解决了多线程的安全性问题
 同步的弊端:较为消耗资源

 同步函数
 同步函数只需要在方法前加synchronized修饰即可
 同步非静态方法的锁是 this
 而同步静态方法的锁是 类名.Class() 因为静态进入内有存时,还没本类对象,只有该类对应的字节码文件对象。
*/
//解决上述程序的线程安全性问题。
//代码如下:
class ThreadDemo3 implements Runnable
{
 private int tick=10;
 //复写Runnable接口的run方法
 public void run()
 {
  while(true)
  { 
   //让线程暂停一会儿后自动回去可执行状态
   try{Thread.sleep(100);}catch(Exception e){}
   synchronized(new Object())
   {
    if(tick>0)
    {
     System.out.println(Thread.currentThread().getName()+"...."+tick--);
    }
   }
  
  }
 }
}
class Test3
{
 public static void main(String[] args)
 {
  ThreadDemo3 th=new ThreadDemo3();
  new Thread(th).start();
  new Thread(th).start();
  new Thread(th).start();
 }
}

 

 

/*
死锁
通常死锁的出现是因为 同步嵌套同步时,锁却不同,
*/

class Test implements Runnable
{
 private boolean flag;
 static Object locka=new Object();
 static Object lockb=new Object();
 Test(boolean flag)
 {
  this.flag=flag;
 }
 public void run()
 {
  while(true)
  {
   if(flag)
  {
   synchronized(locka)//同步用locka锁
   {
    System.out.println("if locka");
    synchronized(lockb)//嵌套同步用lockb锁
    {
     System.out.println("if lockb");    }
   }
  }
  else
  {
   synchronized(lockb)//同步用lockb锁
   {
    System.out.println("else lockb");
    synchronized(locka)//嵌套同步用locka锁
    {
     System.out.println("else locka");
    }
   }
  }
 }
  }
  
}
class DeadLockDemo
{
 public static void main(String[] args)
 {
  new Thread(new Test(true)).start();
  new Thread(new Test(false)).start();
 }
 
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!