• java学习之路---线程(重点)


     1.多线程是一种并发机制的有效手段。进程和线程一样,都是实现并发的一个基本单位。线程是比进程更小的一种实现单位,线程是在进程的基础上的进一步划分。所谓的多线就是在一个进程中产生了多个线程,这些线程可以同时存在,同时运行。
    2.多线程的实现

              1.继承Thread类
              2.实现runnable接口


    3.继承Thread类
    public  class  ThreadDemo  extends  Thread{
          private  String  userName ;
         
              
         
          public  String getUserName() {
                return  userName  ;
         }

          public  void  setUserName(String userName) {
                this . userName  = userName;
         }

         
          public  ThreadDemo(String userName) {
                this . userName  = userName;
         }

          @Override
          public  void  run() {
                for ( int  i=1;i<10;i++){
                  System. out .println(  userName +i);
              }
         }

          public  static  void  main(String[] args) {
               ThreadDemo threadDemo= new  ThreadDemo ( "线程A"  );
               ThreadDemo threadDemo1= new  ThreadDemo ( "线程B"  );
              threadDemo.run();
              threadDemo1.run();
         }

    }

    结果:
    线程A1
    线程A2
    线程A3
    线程A4
    线程A5
    线程A6
    线程A7
    线程A8
    线程A9
    线程B1
    线程B2
    线程B3
    线程B4
    线程B5
    线程B6
    线程B7
    线程B8
    线程B9

    发现并没有实现多线程,如果要正确的启动多线程,则要调用start方法。

    代码:
    public  class  ThreadDemo  extends  Thread{
          private  String  userName ;
         
              
         
          public  String getUserName() {
                return  userName  ;
         }

          public  void  setUserName(String userName) {
                this . userName  = userName;
         }

         
          public  ThreadDemo(String userName) {
                this . userName  = userName;
         }

          @Override
          public  void  run() {
                for ( int  i=1;i<10;i++){
                  System.  out .println( userName  +i);
              }
         }

          public  static  void  main(String[] args) {
               ThreadDemo threadDemo= new  ThreadDemo ( "线程A"  );
               ThreadDemo threadDemo1= new  ThreadDemo ( "线程B"  );
              threadDemo.start();
              threadDemo1.start();
         }

    }

    结果(这只是其中的一种):
    线程A1
    线程B1
    线程A2
    线程B2
    线程A3
    线程B3
    线程A4
    线程A5
    线程A6
    线程A7
    线程B4
    线程A8
    线程A9
    线程B5
    线程B6
    线程B7
    线程B8
    线程B9

    为什么要调用start,而不是调用run方法喃?
    看源码:
      public  synchronized  void  start() {
             /**
             * This method is not invoked for the main method thread or "system"
             * group threads created/set up by the VM. Any new functionality added
             * to this method in the future may have to also be added to the VM.
             *
             * A zero status value corresponds to state "NEW".
             */
             if  ( threadStatus  != 0)
                 throw  new  IllegalThreadStateException();

             /* Notify the group that this thread is about to be started
             * so that it can be added to the group's list of threads
             * and the group's unstarted count can be decremented. */
             group .add(  this );

             boolean  started =  false ;
             try  {
                start0();
                started =  true ;
            }  finally  {
                 try  {
                     if  (!started) {
                         group .threadStartFailed(  this );
                    }
                }  catch  (Throwable ignore) {
                     /* do nothing. If start0 threw a Throwable then
                      it will be passed up the call stack */
                }
            }
        }

         private  native  void  start0();

    返现这里的start0()用了 native ,这个关键字表示调用本机的操作系统函数,因为多线程需要底层操作系统的支持。



    如果一个类继承了Thread类,那么一个对象就只能调用一次,如果调用多次,则会抛出异常

    public  class  ThreadDemo  extends  Thread{
          private  String  userName ;
         
              
         
          public  String getUserName() {
                return  userName  ;
         }

          public  void  setUserName(String userName) {
                this . userName  = userName;
         }

         
          public  ThreadDemo(String userName) {
                this . userName  = userName;
         }

          @Override
          public  void  run() {
                for ( int  i=1;i<10;i++){
                  System.  out .println( userName  +i);
              }
         }

          public  static  void  main(String[] args) {
              ThreadDemo threadDemo=  new  ThreadDemo( "线程A"  );
              ThreadDemo threadDemo1= new  ThreadDemo(  "线程B" );
              threadDemo.start();
              threadDemo.start();
         }

    }
    结果:
    线程A1
    线程A2
    线程A3
    线程A4
    线程A5
    线程A6
    线程A7
    Exception in thread "main"  java.lang.IllegalThreadStateException
         at java.lang.Thread.start(  Thread.java:682 )
         at test.ThreadDemo.main(  ThreadDemo.java:34 )
    线程A8
    线程A9

    所以如果一个类继承Thread类,想要实现多线程,就有单继承的局限性,所以最好实现runnable接口

    4.实现runnable 接口

    class  MyTread  implements  Runnable{
          private   Integer   ticket =10;
          public  void  run() {
              
              fun();
         }
         
          public  synchronized  void  fun(){
                for ( int  i=0;i<100;i++){
                  
                    if ( ticket  >0){
                       System.  out .println( "卖票: ticket=" + ticket --);
                       
                  }
         
              
         }
         }
    };

    public  class  ThreadDemo1{
                public  static  void  main(String[] args) {
                  MyTread myTread=  new  MyTread();
                    new  Thread(myTread).start();
                    new  Thread(myTread).start();
                    new  Thread(myTread).start();
              }
         
    }

    这样写:
    可以实现多线程的访问(下面的结果是因为锁的原因)

    结果:
    卖票: ticket=10
    卖票: ticket=9
    卖票: ticket=8
    卖票: ticket=7
    卖票: ticket=6
    卖票: ticket=5
    卖票: ticket=4
    卖票: ticket=3
    卖票: ticket=2
    卖票: ticket=1

    如果代码改为这样:

    class  MyTread  implements  Runnable{
          private   Integer   ticket =10;
          public  void  run() {
                for ( int  i=0;i<100;i++){
                    if ( ticket  >0)
                  System.  out .println( "票号"  + ticket  --);
                  
              }
              
              
         }
         
    }
    public  class  ThreadDemo1{
                public  static  void  main(String[] args) {
                  MyTread myTread=  new  MyTread();
                    new  Thread(myTread).start();
                    new  Thread(myTread).start();
                    new  Thread(myTread).start();
              }
         
    }
    结果:(不唯一)

    票号10
    票号8
    票号9
    票号6
    票号4
    票号3
    票号2
    票号1
    票号7
    票号5


    5.线程的状态

         线程有五种状态

                             
    创建状态:一个线程被创建后就处于创建状态,此时它拥有了相应的内存空间和其他资源,但是还处于不可运行状态

    就绪状态:当调用线程的时候就进入就绪状态,此时,它将进入线程队列排队,等待CPU服务。

    运行状态:CPU调用该资源,自动调用该线程对象的run方法

    阻塞状态:CPU暂时中止此线程的进行。

    死亡:线程调用stop()或者run()方法运行完成后


    6.线程的相关方法




    应用方法代码:

              取得线程名称:

    class  MyTread  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0)
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );//取得线程名称,如果自己没有给名称,那么程序就会自动付给一个名称

    看源码:


         public  Thread (Runnable target) {
            init(  null  , target,  "Thread-"  nextThreadNum(), 0);
        }

       private   static   synchronized  int  nextThreadNum () {
             return   threadInitNumber  ++;
        }


                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo1 {
                public   static  void  main(String[] args) {
                  MyTread myTread=  new  MyTread();
                    new  Thread(myTread).start();
                    new  Thread(myTread).start();
                    new  Thread(myTread).start();
              }
         
    }
    结果:

    Thread-1票号10
    Thread-0票号9
    Thread-1票号8
    Thread-2票号6
    Thread-0票号7
    Thread-2票号4
    Thread-1票号5
    Thread-2票号2
    Thread-0票号3
    Thread-1票号1

    如果给了名称:

    class  MyTread  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0)
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo1 {
                public   static  void  main(String[] args) {
                  MyTread myTread=  new  MyTread();
                  
                    new  Thread(myTread, "A线程"  ).start();  //自己给线程名称
                    new  Thread(myTread, "like"  ).start();
                    new  Thread(myTread).start();
              }
         
    }
    结果:

    like票号10
    like票号9
    like票号7
    like票号6
    A线程票号8
    Thread-0票号4
    like票号5
    Thread-0票号2
    A线程票号3
    like票号1

    补充:

    java程序启动的时候至少启动两个程序,一个是:main,一个是垃圾回收机制



    线程的休眠:

    class  MyTread  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0){
                         try  {
                            Thread. sleep(1000);//这里休眠1000ms==1S
                       }  catch  (InterruptedException e) {
                            
                            e.printStackTrace();
                       }
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );
                  }
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo1 {
                public   static  void  main(String[] args) {
                  MyTread myTread=  new  MyTread();
                  
                    new  Thread(myTread, "A线程"  ).start();  //自己给线程名称
                    new  Thread(myTread, "like"  ).start();
                    new  Thread(myTread).start();
              }
         
    }

    自己打印结果的时候:就会发现有停顿:

    like票号10
    A线程票号10
    Thread-0票号9
    like票号8
    A线程票号7
    Thread-0票号6
    like票号5
    A线程票号4
    Thread-0票号3
    like票号2
    A线程票号2
    Thread-0票号1
    like票号0
    A线程票号-1

    这里出现了-1,是因为在if(ticket>0)判断的时候,上一个线程还没有 ticket  -- ,而另一个线程就已经进入





    判断线程是否启动:

    class  MyTread  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0){
                         try  {
                            Thread. sleep(1000);
                       }  catch  (InterruptedException e) {
                            
                            e.printStackTrace();
                       }
                   System.  out  .println(Thread. currentThread().getName()+  "票号" +  ticket -- );
                  }
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo2 {
         
           public   static   void  main(String[] args) {
              MyTread myTread=  new  MyTread();
              
         Thread t=   new  Thread(myTread, "A线程"  ); //自己给线程名称
         System.  out .println ( "线程是否启动"  +t.isAlive());
         
         t.start();  //启动线程
         
         System.  out .println ( "线程是否启动"  +t.isAlive());
                new  Thread(myTread, "like"  ).start();
                new  Thread(myTread).start();
         }

    结果:

    线程是否启动false
    线程是否启动true
    like票号10
    A线程票号10
    Thread-0票号9
    A线程票号8
    like票号7
    Thread-0票号6
    A线程票号5
    like票号4
    Thread-0票号3
    A线程票号2
    like票号1
    Thread-0票号0
    A线程票号-1


    线程的强制进行:

    class  MyTread  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0){
                         try  {
                            Thread. sleep(1000);
                       }  catch  (InterruptedException e) {
                            
                            e.printStackTrace();
                       }
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );
                  }
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo2 {
         
           public   static   void  main(String[] args) {
              MyTread myTread=  new  MyTread();
              
         Thread t=   new  Thread(myTread, "A线程"  ); //自己给线程名称
         System.  out .println(  "线程是否启动"  +t.isAlive());
         
         t.start();  //启动线程
         
           for (  int  i=0;i<10;i++){
                if  (i>2){
                    try  {
                       t.join();  //线程的强制惊醒
                  }  catch  (InterruptedException e) {
                         //  TODO  Auto-generated catch block
                       e.printStackTrace();
                  }
              }
         }
         System.  out .println(  "线程是否启动"  +t.isAlive());
                new  Thread(myTread, "like"  ).start();
                new  Thread(myTread).start();
              
              
         }

    }

    结果:

    线程是否启动false
    A线程票号10
    A线程票号9
    A线程票号8
    A线程票号7
    A线程票号6
    A线程票号5
    A线程票号4
    A线程票号3
    A线程票号2
    A线程票号1
    线程是否启动false

    为什么第二次判断也是false,那是因为,线程A已经执行完毕,所以已经死亡,自然是false


    线程的中止:
    class  MyTread1  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0){
                         try  {
                            Thread. sleep(3000);
                       }  catch  (InterruptedException e) {
                            System.  out  .println( "A线程被中止"  );
                              return  ;
                       }
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );
                  }
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo2 {
         
           public   static   void  main(String[] args) {
              MyTread1 myTread=  new  MyTread1();
              
         Thread t=   new  Thread(myTread, "A线程"  ); //自己给线程名称
         System.  out .println(  "线程是否启动"  +t.isAlive());
         
         t.start();  //启动线程
           try  {
              Thread. sleep(2000);
         }  catch  (InterruptedException e) {
                //  TODO  Auto-generated catch block
              e.printStackTrace();
         }
         
         t.interrupt();
         
         System.  out .println(  "线程是否启动"  +t.isAlive());
                new  Thread(myTread, "like"  ).start();
                new  Thread(myTread).start();
              
              
         }

    }
    结果:
    线程是否启动false
    线程是否启动true
    A线程被中止
    like票号10
    Thread-0票号9
    like票号8
    Thread-0票号7
    like票号6
    Thread-0票号5
    like票号4
    Thread-0票号3
    like票号2
    Thread-0票号1



    后台线程:

    t.setDaemon(  true );



    7.线程的优先级

    class  MyTread1  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0){
                         try  {
                            Thread. sleep(100);
                       }  catch  (InterruptedException e) {
                            System.  out  .println( "A线程被中止"  );
                       }
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );
                  }
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo2 {
         
           public   static   void  main(String[] args) {
              MyTread1 myTread=  new  MyTread1();
              
         Thread t=   new  Thread(myTread, "A线程"  ); //自己给线程名称
         
         Thread t1=      new  Thread(myTread, "like"  );
         Thread t2=      new  Thread(myTread);
         
              t.setPriority(Thread.  MAX_PRIORITY  ); //设置线程优先级,最大10
              t1.setPriority(Thread.  MIN_PRIORITY  );最小1
              t2.setPriority(Thread.  NORM_PRIORITY  );5
         
              
              t1.start();
              t.start();  //启动线程
              t2.start();
              
         }

    }

    结果:
    like票号10
    A线程票号8
    Thread-0票号9
    Thread-0票号7
    like票号6
    A线程票号5
    Thread-0票号4
    like票号3
    A线程票号2
    Thread-0票号1
    A线程票号0
    like票号-1

    这说明不是绝对那个线程的优先级高,就调用那个,而是要看CPU的调度



    public   class  ThreadDemo2 {
         
           public   static   void  main(String[] args) {
    //        MyTread1 myTread=new MyTread1();
    //        
    //   Thread t= new Thread(myTread,"A线程");//自己给线程名称
    //   
    //   Thread t1=    new Thread(myTread,"like");
    //   Thread t2=    new Thread(myTread);
    //   
    //        t.setPriority(Thread.MAX_PRIORITY);//设置线程优先级
    //        t1.setPriority(Thread.MIN_PRIORITY);
    //        t2.setPriority(Thread.NORM_PRIORITY);
    //   
    //        
    //        t1.start();
    //        t.start();//启动线程
    //        t2.start();
              
              System.  out  .println(Thread.currentThread().getPriority());  //获取主方法的优先级
              
         }

    }

    结果:
    5


    8.线程的礼让:(让当前的线程暂时让个其他线程)

    class  MyTread1  implements  Runnable{
           private   Integer   ticket =10;
           public   void  run() {
                for  ( int  i=0;i<100;i++){
                    if  ( ticket  >0){
                       System.  out  .println(Thread.currentThread().getName()+  "----->"  ); //获取线程的名字
                         if  ( ticket  ==3){
                            System.  out  .print( "线程礼让:"  );
                             Thread.currentThread ().yield();
                       }
                   System.  out  .println(Thread.currentThread().getName()+  "票号"  + ticket  -- );
                  }
                  
              }
              
              
         }
         
    }
    public   class  ThreadDemo2 {
         
           public   static   void  main(String[] args) {
              MyTread1 myTread=  new  MyTread1();
              
         Thread t=   new  Thread(myTread, "A线程"  ); //自己给线程名称
         
         Thread t1=      new  Thread(myTread, "like"  );
         Thread t2=      new  Thread(myTread);
         
              t.setPriority(Thread.  MAX_PRIORITY  ); //设置线程优先级
              t1.setPriority(Thread.  MIN_PRIORITY  );
              t2.setPriority(Thread.  NORM_PRIORITY  );
              t1.start();
              t.start();  //启动线程
              t2.start();
              
         }

    }

    结果:
    A线程----->
    like----->
    Thread-0----->
    Thread-0票号8
    A线程票号10
    like票号9
    Thread-0----->
    like----->
    A线程----->
    A线程票号5
    like票号6
    like----->
    like票号4
    like----->
    线程礼让:like票号3
    like----->
    like票号2
    like----->
    like票号1
    Thread-0票号7
    A线程----->
    A线程票号0

    看看结果:当线程like让出当前线程,但是下一个执行的线程还是like线程,这说明线程的礼让不是绝对的,不是礼让了就一定会让给其他线程


  • 相关阅读:
    poj.1703.Find them, Catch them(并查集)
    uva.10020 Minimal coverage(贪心)
    Hdu.1325.Is It A Tree?(并查集)
    1455.Solitaire(bfs状态混摇)
    hdu.1430.魔板(bfs + 康托展开)
    hdu.1254.推箱子(bfs + 优先队列)
    hihoCoder挑战赛11.题目4 : 高等理论计算机科学(LCA)
    Codeforces Round #302 (Div. 2).C. Writing Code (dp)
    hdu.1198.Farm Irrigation(dfs +放大建图)
    hdu.1111.Secret Code(dfs + 秦九韶算法)
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3433051.html
Copyright © 2020-2023  润新知