zoukankan      html  css  js  c++  java
  • 多线程笔记

    【掌握的】

    1.两种方式创建线程:(继承,实现)

    2.继承和实现的区分

    3.线程的生命周期 

    4.不同状态下,所对应的方法。【通过哪些方法,可以让线程达到某个状态。】

    5.同步代码块,同步方法。

    ----------------------

    1.学习多线程的原因?

      生活中:

       程序:  一个完整的功能代码。(方法,没有被运行)

       进程:  一个完整的功能代码。(方法,被运行)

       线程:  进程包含线程。


      好处:提高代码的执行效率。总是有一些功能是需要同时执行的,那就需要多线程。


    2.主线程:
     
       -----执行main方法里的代码。

      普通线程
       ------run 方法里的代码。


    3.完成线程的步骤:


       A. 编写线程类:(1.通过继承)

       B. 重写run方法:

       C. 创建线程对象,调用start方法,开启线程。


      补充:

       (1) 线程对象.run();  没有开启线程,只是在调用线程对象的run()方法。                  
             线程对象.start(); 线程开启的标志,自动调用run()方法
       
       (2) 调用start()方法就立刻执行run()方法吗?


            线程对象.start(); ----当前线程所处的状态是“就绪状态”

                 真正执行run();----当前线程所处的状态是“运行状态”

            ----“就绪状态” 和“运行状态” 之间,间隔多久,不清楚。
     

       (3)线程  【默认命】和【指定名】。


            普通线程的默认名:Thread-变量    ----变量static的,从0开始计数

                主线程默认名:main


            
             // private String name;   //1.接收外界传入的参数,完成线程名。
      // public Thread1(String name){
      //   this.name=name;
      // }
     
       public Thread1(String name){//2.调用父类有参,完成线程命名。
        super(name);
       }

     public void run() {
         // Thread.currentThread().setName(name);
      for (int i = 1; i <= 10; i++) {
       System.out.println
       (Thread.currentThread().getName()+"--->"+i);
      }
     }


      【2.通过实现完成线程】
        
       A.编写线程类:


       B.。重写run()方法


       C。创建线程实现类对象,

           创建线程对象,

           线程对象调用方法,开启线程。

          
       补充: (1.) Thread 实现 Runnable接口
     
              (2.)Thread  th

                    Thread2  th2
              都实现Runnable接口 ,在th .start();---th2.run()被执行。【代理模式】
        

              (3.)继承方式, VS 实现方式  哪种线程类更好?

                     实现方式 好:

                     1.可以多实现

                     2.数据共享。

                    【例子:3个窗口同时销售5张火车票】
                   
                
                    【继承方式:】
    public class ThreadPiao extends Thread {
            private int piao=5;
     
     public void run() {
      
        for(int i=1;i<=100;i++){
         if(piao>0){
          System.out.println
          (Thread.currentThread().getName()+"---"+piao--);
         }
        }
     
     }
    }
     
          【测试代码】
                    new ThreadPiao().start();
      new ThreadPiao().start();
      new ThreadPiao().start();

                  【实现方式】
    public class ThreadP implements Runnable {

     private int piao=5;
     
     public void run() {
       for(int i=1;i<=100;i++){
          if(piao>0){
           System.out.println
           (Thread.currentThread().getName()+"---"+piao--);
          }
         }
     }

    }
              【测试代码】
                    ThreadP tp=new ThreadP();
      new Thread(tp).start();
      new Thread(tp).start();
      new Thread(tp).start(); 


        问题:继承方式,可不可以只new 1个线程对象,然后调用3次start()方法?

           

    4.线程状态/生命周期:
       A.新生状态:   new 线程类();
       B.就绪状态:   start();  【有被执行的资格,但是还没有被cpu调度;队列】
       C.运行状态:   run();   
       D.阻塞状态:  sleep():  礼让 yi  ();  强制 join();
       D.死亡状态:A。正常线程结束 B。发生异常,产生异常对象,没有被截获。

                  C。线程自身调用了Stop()。---不被使用


     4.1新生状态:
      
         创建线程对象,可以调用无参,有参(给线程命名)
         ---可以获得到的信息:

           1.获得线程对象。名字 Thread.currentThread().getName()

           2.设置或获得当前线程的优先级:
             th.setPriority(9);
      System.out.println("线程优先级最大是:"+Thread.MAX_PRIORITY);
      System.out.println("线程优先级最大是:"+Thread.MIN_PRIORITY);
      System.out.println("th1的线程优先级是:"+th.getPriority());
      
       4.2就绪状态:

            是否处于就绪状态:Thread.currentThread().isAlive()
            
       4.3运行状态:

         程序执行run();【有被执行的资格,同时也被CPU调度。但是至于什么时间被执行的,不清楚】


      4.4阻塞状态:

          【线程强制执行:join()】

          for (int i = 1; i <=10; i++) {
       if(i==3){
        try {
         th.join();
        } catch (InterruptedException e) {
         e.printStackTrace();
        }
       }
             System.out.println(Thread.currentThread().getName()+"--"+i);
      }
             说明:普通线程强制抢占了cpu资源。

                   主线程:由原来的运行状态----》阻塞状态---就绪状态---运行状态

                   普通线程:直接运行结束。

             使用场合:线程有明确的【完成先后顺序】。  
       

          【线程休眠:sleep()】

               for (int i = 1; i <=10; i++) {
       if(i==3){
         Thread.sleep(3000);//单位是毫秒
       }
             System.out.println(Thread.currentThread().getName()+"--"+i);
        }

            说明:(1)当前线程休眠:由原来的运行状态----》阻塞状态---就绪状态---运行状态
                       ---休眠时间结束,进入到就绪状态,等待cpu调度。

                  (2)中途阻止休眠:(了解)    
                       【例子:】
                       终止休眠: 1. th.interrupt();
                                 2.  在异常捕获的时候,出现return。


          【线程礼让:】

                for (int i = 0; i < 10; i++) {
       if(i==3){
        Thread.yield();
        System.out.println("线程礼让一次");
       }
       System.out.println(i);
      }
                 说明:让出当前这次cpu资源:线程状态不阻塞---直接进行就绪状态--运行状态。


    5.线程安全:

          多线程同时操作数据资源,会出现数据不正确。所需线程同步。
      

        第一种方式:同步代码块  ---使用在线程中。

     public void run() {
       
     for (int i = 1; i <=100; i++) {
      synchronized(this){
       if(piao>0){
        try {
         Thread.sleep(1000);
        } catch (InterruptedException e) {
         e.printStackTrace();
        }
     System.out.println(Thread.currentThread().getName()+"--"+piao--);
       }
      }
     }
      
     }

        第二种方式:同步方法:
             
     public void run() {
       
        for (int i = 1; i <=100; i++) {
      
        maip();
      
       }
      
     }

         public synchronized void maip(){
      if(piao>0){
       try {
        Thread.sleep(1000);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
     System.out.println(Thread.currentThread().getName()+"--"+piao--);
      }
     }

  • 相关阅读:
    hdu 14004
    hdu 1850 基础尼姆博奕
    hdu 1847 sg函数
    hdu 2177
    hdu 1527
    hdu 2897
    hdu 2516 取石子游戏
    hdu 1525 Euclid's Game
    hdu 2063
    hdu 1281 棋盘游戏
  • 原文地址:https://www.cnblogs.com/zhuhuibiao/p/9313876.html
Copyright © 2011-2022 走看看