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线程,这说明线程的礼让不是绝对的,不是礼让了就一定会让给其他线程


原文地址:https://www.cnblogs.com/fuhaots2009/p/3433051.html