黑马程序员-Java多线程

1. 进程与线程

     进程:正在运行中的程序。每个进程拥有自己的一整套变量。
     线程:进程中一条执行路径。线程共享数据。每个线程在栈区中都有自己的执行空间,自己的方法区、自己的变量。
 
 
2. 多线程
      一个进程中至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序。
 
     线程运行必须要通过类中指定的方法开启:start方法
          start方法:1)启动了线程     2)让jvm调用了run方法
 
     创建线程的方式:
     |--继承Thread类
     步骤:
          1. 定义类继承Thread类;
          2. 复写run方法,将要让线程运行的代码都存储到run方法中;
          3. 通过创建Thread类的子类对象,创建线程对象;
          4. 调用线程的start方法,开启线程,并执行run方法。
 
     |--实现Runnable接口
          1. 定义类实现Runnable接口;
          2. 覆盖接口中的run方法(用于封装线程要运行的代码);
          2. 通过Thread类创建线程,并将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数;
               为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
          3. Thread类对象调用start方法开启线程。
 
     为什么要有Runnable接口的出现?
     1. 通过继承Thread类的方式,可以完成多线程的建立。但是如果一个类已经有了自己的父类,就不可以继承Thread类,因为Java单继承的局限性。
          而实现Runnable接口可以避免单继承的局限性。
     2. 其实是将不同类中需要被多线程执行的代码进行抽取。将多线程要运行的代码的位置单独定义到接口中,为其他类进行功能扩展提供了前提。
          所以Thread类在描述线程时,内部定义的run方法,也来自于Runnable接口。
 
     线程运行状态:
     被创建: start()
     运行: 具备执行资格,同时具备执行权。
     冻结: sleep(time), wait()-notify()唤醒;线程释放了执行权,同时释放执行资格。
     阻塞:具备执行资格,没有执行权。
     消亡:stop()
3. 多线程安全
     多线程安全问题的原因:
          因为cpu的快速切换,哪个线程获得了cpu的执行权,哪个线程就执行。
                  1)多个线程在操作共享数据
                  2)有多条语句对共享数据进行运算
     
     解决安全问题的原理:
          只要将操作共享数据的语句在某一时段让一个线程执行,在执行过程中,其他线程不能进来执行。
 
4. 线程同步
     好处:解决了线程安全问题。
     弊端:相对降低性能,因为判断锁需要消耗资源,产生了死锁问题。
     
     定义同步前提:
          1)必须要有两个或两个以上的线程,才需要同步。
          2)多个线程必须保证使用的是同一个锁。
 
     同步函数:将同步关键字定义在函数上,让函数具备了共同性。
          1)同步函数使用的锁是this锁。
          2)当同步函数被static修饰时,锁对象是该类的字节码文件对象:类名.class
 
     同步函数和同步代码块的区别?
          1. 锁对象:同步代码块使用的锁可以是任意对象;同步函数分两种情况。
          2. 在一个类中只有一个同步,可以使用同步函数;如果有多同步,必须使用同步代码块。
 
     同步死锁:
          通常只要将同步进行嵌套,就可以看到现象。同步函数中有同步代码块,同步代码块中有同步函数。
 
     等待唤醒机制:(因为这些方法都需要定义在同步中,所以三个方法都定义在Object类中)
          wait:将同步中的线程处于冻结状态,释放执行权,释放执行资格。同时将线程对象存储到线程池中。
          notify:唤醒线程池中某一个等待线程。
          notifyAll:唤醒的是线程池中的所有线程。
 
     wait和sleep区别:
          wait(可以指定时间也可以不指定时间;不指定时间只能由对应的notify或者notify唤醒):线程会释放执行权,而且会释放锁。
          sleep(必须指定时间,时间到自动从冻结状态转成运行状态):线程会释放执行权,但不释放锁。
 
     Lock接口:将锁对象封装成对象来处理
          同步是隐式的锁操作,而Lock对象是显示的锁操作,它的出现代替了同步。
          Lock接口中没有直接操作等待唤醒的方法,而是将这些方式单独封装到了一个对象中:Condition。
          Condition接口:await(),     signal(),     signalAll()
 
 
     
 
 
 
 
 
posted @ 2015-03-19 20:38  troy健  阅读(220)  评论(0编辑  收藏  举报