A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 心在左边跳 于 2015-7-6 16:31 编辑

线程概述
进程:是正在执行中的程序。每个进程执行都有个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。(进程标志执行内存空间)
线程:是进程中独立的控制单元,线程在控制进程执行。(多个线程抢占执行优先权,CPU执行谁,谁就运行。在同一时刻,只有一个程序运行,除了多核可以同时执行线程。CPU在快速切换,以达到同时运行效果)
一个进程之至少有个线程。

JVM 启动时会有个进程java.exe。该进程至少有个线程负责java程序执行。而且该线程运行的代码存在于main方法中。该线程称为主线程。
扩展:JVM起点不止一个线程,还有负责垃圾回收机制的线程。

创建线程-继承Thread类
  • 定义类,继承Thread
  • 重写run()方法
  • 调用线程start()方法。该方法2个作用,启动线程,JVM调用run方法。run和start特点为什么要覆盖run()方法?
    Thread类用来描述线程:
    该类定义一个功能,用来存储线程要运行的代码,该存储功能就是run()方法。
    thread.start//开启线程并执行该线程的代码
    thread.run//仅仅对象调用方法,而线程创建了,并没有运行。
线程的运行状态

被创建---start()---运行----sleep or wait---冻结(放弃执行资格)----notify()-----临时阻塞状态

运行----stop or run结束---消亡

临时阻塞状态:具备运行资格,但没有执行权。

获取线程对象和名称

线程都有自己的名称,Thread-编号,编号从0开始
getName()--setName()

  1. class Test extends Thread {
  2. public Test(String name){
  3. super(name);
  4. }
  5. }
复制代码
Thread.currentTread() //获取当前线程对象
局部变量在每个线程区域当中都有独立一份
声明Runnable接口
创建线程的第二种方法:实现runnable接口
  • 定义类实现Runnable接口
  • 覆盖Runnable中run方法
  • 通过Thread建立线程对象
  • 将Runnable接口子类对象作为参数传递给Thread的构造函数
  • 调用Thread的start开启线程调用Runnable接口子类的run方法。
    1. class Ticket implements Runnable {
    2. public void run(){
    3. }
    4. }
    5. Ticket t= Ticket();
    6. new Thread(t).start();
    7. new Thread(t).start();
    复制代码

    实现方式和继承方式有什么区别?
    实现方法避免了单继承的局限性,在定义线程时,建议使用实现方法。

    多线程安全问题

    synchronized(对象){
    需要被同步的代码

    对象如同锁,当线程获取锁时,置锁的状态为false,不让其他线程进来,出来后,锁置为true。
    弊端:多个线程需要判断锁,消耗资源。
    好处:解决了多线程的安全问题。


    • 明确哪些代码是多线程运行代码
    • 明确共享数据
    • 明确多线程运行代码中哪些语句是操作共享数据的。同步函数同步2种表现形式:同步函数,同步代码块。
      让函数具备同步性
      public synchronized void add(){}同步函数的锁是this同步函数被对象调用,那么函数有一个所属对象引用,就是this.所以同步函数使用的锁是this.
    1. public class Ticket implements Runnable {
    2. private int tick=1000;
    3. boolean flag=true;
    4. @Override
    5. public void run() {
    6. if (flag){
    7. while (true){
    8. synchronized (this) {
    9. if(tick>0){
    10. try{Thread.sleep(10);}catch (Exception e){e.printStackTrace();}
    11. System.out.println(Thread.currentThread().getName()+".....CODE....."+tick--);
    12. }
    13. }
    14. }}else {
    15. while (true){
    16. this.show();
    17. }
    18. }
    19. }
    20. public synchronized void show() {
    21. if(tick>0){
    22. try{Thread.sleep(10);}catch (Exception e){e.printStackTrace();}
    23. System.out.println(Thread.currentThread().getName()+".....SHOW....."+tick--);
    24. }
    25. }
    26. public static void main(String[]args){
    27. Ticket t = new Ticket();
    28. Thread t1= new Thread(t);
    29. Thread t2= new Thread(t);
    30. t1.start();
    31. try{Thread.sleep(1);}catch (Exception e){e.printStackTrace();}
    32. t.flag=false;
    33. t2.start();
    34. }
    35. }
    复制代码
    静态同步函数的锁是Class对象

    public static synchronized show()
    静态方法中不可能有this,静态进内存时,内存没有本类对象,但一定有该类对应的字节码文件对象。类名.class 该对象的类型是Class.
    静态同步方法,使用的锁是该方法所在类的字节码文件对象,类名.class

    单例设计模式–懒汉式

    延迟加载的懒汉式

    1. class Single {
    2.     private static Single s=null;
    3.     private Single(){}
    4.     public static  Single getInstance(){
    5.         if(s==null){//双重判定解决效率问题
    6.             synchronized(Single.class){
    7.                  s=new Single();
    8.             }
    9.         }
    10.         return s;
    11.     }
    12. }
    复制代码
    死锁

    同步中嵌套同步,而锁不同

    1. class DeadLock implements Runnable {
    2.     private boolean flag;
    3.     public  DeadLock(boolean flag) {
    4.             this.flag=flag;
    5.     }
    6.     public void run(){
    7.         if(flag){
    8.             synchronized(MyLock.locka){
    9.                 System.out.println("if locka");
    10.                 synchronized(MyLock.lockb){
    11.                     System.out.println("if lockb");
    12.                 }
    13.             }
    14.         }else{
    15.             synchronized(MyLock.lockb){
    16.                 System.out.println("else lockb");
    17.                 synchronized(MyLock.locka){
    18.                     System.out.println("else locka");
    19.                 }
    20.             }
    21.         }
    22.     }
    23.     public static void main(String[] args){
    24.         Thread t1=new Thread(new DeadLock(true));
    25.         Thread t2=new Thread(new DeadLock(false));
    26.         t1.start();
    27.         t2.start();
    28.     }
    29. }
    30. class MyLock{
    31.     public static Object locka=new Object();
    32.     public static Object lockb=new Object();
    33. }
    复制代码
    线程间通信

    多个线程操作同一个资源,但是操作动作不同
    input---资源---output

    wait(),notify(),notifyAll()为何定义在Object类中
    线程运行时内存会建立线程池,等待的线程存储在线程池。notify唤醒线程池中线程。
    r.wait() //锁对象调用wait,使持有该锁的线程等待。
    wait(),notify,notifyAll都使用在同步中,因为对持有监视器(锁)的线程操作。
    所以要使用在同步中,因为只有同步才有锁。
    这些方法在操作同步中线程时,都必须要标识他们所操作线程持有锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用方法定义在object中。

    1. public class Res {
    2.     private String name;
    3.     private String sex;
    4.     private boolean flag=false;
    5.     public synchronized void set(String name,String sex){
    6.         if(flag)
    7.             try{this.wait();}catch(Exception e){e.printStackTrace();}
    8.             this.name=name;
    9.             this.sex=sex;
    10.             flag=true;
    11.             this.notify();
    12.     }
    13.         public synchronized void out(){
    14.             if(!flag)
    15.                 try{this.wait();}catch(Exception e){e.printStackTrace();}
    16.                 System.out.println(name+"----"+sex);
    17.                 flag=false;
    18.                 this.notify();
    19.     }
    20.         public static void main(String[] args) {
    21.             Res r=new Res();
    22.             Input in= new Input(r);
    23.             Output out=new Output(r);
    24.             Thread t1=new Thread(in);
    25.             Thread t2=new Thread(out);
    26.             t1.start();
    27.             t2.start();
    28.         }
    29. }
    30. class Input implements Runnable{
    31.     private Res r;
    32.     public Input(Res r) {
    33.         this.r=r;
    34.     }
    35.     @Override
    36.     public void run() {
    37.         int x=0;
    38.         while(true){
    39.             if(x==0){
    40.                 r.set("John", "man");
    41.             }else{
    42.                 r.set("lili", "woman");
    43.             }
    44.             x=(x+1)%2;
    45.         }
    46.     }   
    47. }
    48. class Output implements Runnable{
    49.     private Res r;
    50.     public Output(Res r) {
    51.         this.r=r;
    52.     }
    53.     @Override
    54.     public void run() {
    55.         while(true){
    56.             r.out();
    57.         }
    58.         }
    59. }
    复制代码
    毕向东老师视频知识点笔记---多线程(2)

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马