黑马程序员----多线程

来源:互联网 发布:js垂直轮播广告幻灯片 编辑:程序博客网 时间:2024/05/30 04:24

多线程

 ------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------


进程:正在执行的程序。

线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)进程中至少有一个线程。


创建线程的两种方式:

①:继承Thread类:

    步骤:

          1、定义一个类继承Thread;

          2、复写Thread类中的run()方法;

          3、调用线程的start()开启线程,并调用执行run()方法。

②:实现Runnable接口:

    步骤:

         1、定义一个类实现Runnable接口;

         2、覆盖Runnable接口中的run()方法;

         3、通过Thread类创建线程对象;

         4、将Runnable接口的子类对象作为实际参数传递给Thread;

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

 

同步的所有特性   

 

线程的状态。

  1,被创建。

  2,运行。

  3,冻结。(冻结状态的特点:放弃了执行资格。 ①、sleep(time) sleep时间到就又开始;②、wait() 当调用notify()时线程开始运行)

  4,消亡。

  5,还有一种特殊的状态:临时状态。

      该临时状态的特点:具备了执行资格,但不具备执行权,多线程具备随机性。因为是由cpu不断的快速切换造成的。就有可能会产生多线程的安全问题。

问题产生的原因

几个关键点:

  1,多线程代码中有操作共享数据。

  2,多条语句操作该共享数据。

当具备两个关键点时,有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。就会发生数据错误。

解决方法:

  当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。

 

Java对于多线程的安全问题提供了专业的解决方式----同步代码块。

同步的原理:就是将部分操作功能数据的代码进行加锁。

同步的表现形式:

  1,同步代码块。

    synchronized(对象)

    {

      需要被同步的代码

    }

    对象如同锁。持有锁的线程可以在同步中执行。

  2,同步函数。

    两者的不同:

      同步代码块使用的锁是任意对象。

      同步函数使用的锁是this

     注意:对于static的同步函数,使用的锁不是this。 类名.class 是该类的字节码文件对象。

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

同步的弊端:较为消耗资源。同步嵌套后,容易死锁。

*同步使用的前提:

  1,必须是两个或者两个以上的线程。

  2,必须是多个线程使用同一个锁。

     这是才可以称为这些线程被同步了。

 

停止线程:

原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。

    1,定义结束标记。

    2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态。

    强制结束冻结状态:interrupt()目的是线程强制从冻结状态恢复到运行状态。但是会发生InterruptedException异常。

 

线程中一些常见方法:

  setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。

  join():等待该线程结束。当A线程执行到了B.join方法时,A就会处于冻结状态。A什么时候运行?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。

 


  线程间的通信:多个线程在操作同一个资源,但是操作的动作却不一样。

                      1、将资源封装成对象;

                      2、将线程执行的任务也封装成对象。



     等待唤醒机制:

     也就是常见的生产者消费者问题。

  1.当多个生产者消费者出现时,需要让获取执行权的线程判断标记。通过while完成。

  2.需要将对方的线程唤醒。仅仅用notify,是不可以的。因为有可能出现只唤醒本方。有可能会导致,所有线程都等待。所以可以通过notifyAll的形式来完成 。

  wait():释放cpu执行权,释放锁。
  sleep():释放cpu执行权,不释放锁

 

JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。

  1,将synchronized 替换成了Lock接口。将隐式锁,升级成了显示锁。

       获取锁:lock();

       释放锁:unlock();通常定义在finally中。

       获取Condition对象:newCondition();

  2,将Object中的waitnotifynotifyAll方法都替换成了ConditionawaitsignalsignalAll。和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立waitnotify方法。现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个lock锁上可以有多个Condition对象。

 

同步中嵌套同步。

class Ticket implements Runnable{

  private  int tick = 1000;

  Object obj = new Object();

  boolean flag = true;

  public  void run(){

    if(flag){

      while(true){

        synchronized(obj){

           show();

        }

      }

    }

    else

    while(true)

    show();

  }

  public synchronized void show()//this{

    synchronized(obj){

      if(tick>0){

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

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

      }

    }

  }

}

class  DeadLock{

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

  }

}



0 0
原创粉丝点击