zoukankan      html  css  js  c++  java
  • JAVA基础-多线程

    线程:一个正在执行的程序。
    多线程存在的意义: 
    程序运行中至少有两个线程在运行,一个是主函数的主线程,另一个是垃圾回收的线程。
    线程创建方式一:
    继承Thread类.要覆盖其run方法,调用线程的start方法.
    作用:1.启动线程
          2.运行run方法。目的是将自定义的代码存储在run方法中,让线程运行
    cpu每次只执行一个程序,只是在快速的不同线程间切换,表现了多线程的随机性
    
    class demo extends Thread{
      public void run(){
      }
    }
    
    run方法用于存储线程要运行的代码。
    
    demo demo=new demo();创建对象就创建了一个线程。
    
    
    run方法和 start方法
    
    run方法  仅仅是对象调用方法,并没有运行线程
    start方法  是开启线程并且执行线程中的run方法

    线程都有自己默认的名称:
    获取线程名称的方法。Thread.currentThread().getName()
    
    currentThread() 获取当前线程对象
    getName()   获取线程名称 
    
    设置线程名称 SetName(); 或者构造方法传参

    创建线程的第二种方式:实现Runnable接口。
    
    创建线程 
    
    Thread t=new Thread(new 对象名());
    
    步骤:
    1,定义类实现Runnable接口。
    2,覆盖接口中的run方法(用于封装线程要运行的代码)。
    3,通过Thread类创建线程对象;
    4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。
          为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
    5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
    Ticket t=new Ticket();
    /*
    直接创建Ticket对象,并不是创建线程对象。
    因为创建对象只能通过new Thread类,或者new Thread类的子类才可以。所以最终想要创建线程。既然没有了Thread类的子类,就只能用Thread类。
    Thread t1=new Thread(t);//创建线程。
    只要将t作为Thread类的构造函数的实际参数传入即可完成线程对象和t之间的关联
    
    实现方式和继承方式有什么区别?
    继承Thread类:线程代码块存放在Thread子类的run方法中
    实现Runnable,线程代码存放在接口的子类的run方法中,可以被多实现。
    
    
    继承方式有局限性。要被实现多线程的一个类 如果继承了父类 就不能再继承Thread类。
    

    多线程安全:
    安全产生的原因:当多条语句在操作同一个共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,
    另一个线程参与进来执行。导致共享数据的错误。
    
    解决办法:
    对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
    
    方式:同步代码块:
    synchronized(对象),火车卫生间案例  
    {
      需要被同步的代码。(共享数据)
    }
    
    对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程,即使获取cpu的执行权,也进不去,因为没有获取锁。
    
    
    同步的前提:
    1.必须要有两个或者两个以上的线程
    2.必须多个线程必须使用同一个锁。
      必须保证同步中只能有一个线程在运行。
    
    
    好处:解决了线程的安全问题
    
    弊端:消耗了资源,多个线程需要判断锁。
    
    
    线程间通信:多个线程在操作同一个资源,但是操作的动作不同。
    
    1.是不是两个或两个以上的线程。解决办法 两个线程都要被同步。
    2.是不是同一个锁。解决办法 找同一个对象作为锁。
    
    等待唤醒机制。
    
    wait后,线程就会存在线程池中,notify后就会将线程池中的线程唤醒。
    notifyAll();唤醒线程池中所有的线程。
    实现方法 :
    
    给资源加个标记 flag   
    
    synchronized(r)
    {
     while(r.flag)//多个生产者和消费者   if(r.flag)//一个生产者和消费者
      r.wait();
      代码
       r.flag=true;
      r.notify();
      r.notifyAll();
    }
    
    上面三种方法都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。
    
    为什么这些操作线程的方法要定义在object类中呢?
    因为这些方法在操作同步中线程的是偶,都必须要表示它们所操作线程只有的锁。只有同一个锁上的被等待线程,可以被
    同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。
    
    也就是说,等待和唤醒必须是同一个锁,而锁可以是特意对象,可以被任意对象调用的方法定义在Object类中。
    


  • 相关阅读:
    关于request对象的parameter和attribute
    EL表达式知识点总结
    隐藏基于Dialog的MFC的主窗体
    VLD 无法打印堆栈调用情况
    javascript对象属性的命名规则
    javascript中boolean类型和其他类型的转换
    javascript中对象访问自身属性的方式
    java与C++相比增加和缺少的特性--持续更新
    java基础算法(一):最大子序列和问题的多种算法思路
    Jconsole或者VisualVM监控远程主机(阿里云,jdk11或者8)
  • 原文地址:https://www.cnblogs.com/chun2015/p/4949171.html
Copyright © 2011-2022 走看看