• 黑马程序员java笔记之二多线程


    java中实现多线程操作有两种手段,一种继承自Thread类,另一种是实现Runnable接口。

     一、继承Thread

        Thread类是在java.lang包中定义的,一个类只要继承了Thread类,此类就称为多线程实现类。在Thread子类中,必须明确地覆写Thread类中的run()方法,此方法为线程的主体。
    1. <span style="font-size:18px;"class MyThread extends Thread{    // 继承Thread类,作为线程的实现类  
    2.     private String name ;        // 表示线程的名称  
    3.     public MyThread(String name){  
    4.         this.name = name ;        // 通过构造方法配置name属性  
    5.     }  
    6.     public void run(){    // 覆写run()方法,作为线程 的操作主体  
    7.         for(int i=0;i<10;i++){  
    8.             System.out.println(name + "运行,i = " + i) ;  
    9.         }  
    10.     }  
    11.        }  
    12.      public class ThreadDemo01{  
    13.         public static void main(String args[]){  
    14.             MyThread mt1 = new MyThread("线程A ") ;     // 实例化对象  
    15.             MyThread mt2 = new MyThread("线程B ") ;     // 实例化对象  
    16.             mt1.run() ;    // 调用线程主体  
    17.             mt2.run() ;    // 调用线程主体  
    18.      }  
    19. }</span>  


    二、实现Runnable接口,Runnable接口中只定义了,一个抽象方法。

           

    1. class MyThread implements Runnable{    // 实现Runnable接口,作为线程的实现类  
    2.            private String name ;        // 表示线程的名称  
    3.   
    4.         public MyThread(String name){  
    5.             this.name = name ;        // 通过构造方法配置name属性  
    6.         }  
    7.         public void run(){    // 覆写run()方法,作为线程 的操作主体  
    8.             for(int i=0;i<10;i++){  
    9.                 System.out.println(name + "运行,i = " + i) ;  
    10.             }  
    11.         }  
    12.        }  
    13.         public class RunnableDemo01{  
    14.             public static void main(String args[]){  
    15.                  MyThread mt1 = new MyThread("线程A ") ;     // 实例化对象  
    16.                 MyThread mt2 = new MyThread("线程B ") ;     // 实例化对象  
    17.                 Thread t1 = new Thread(mt1) ;        // 实例化Thread类对象  
    18.                 Thread t2 = new Thread(mt2) ;        // 实例化Thread类对象  
    19.                 t1.start() ;    // 启动多线程  
    20.                 t2.start() ;    // 启动多线程  
    21.         }  
    22.     }  

    三、线程间通信:  多个线程在操作同一个资源,但是操作的动作不同。等待唤醒机制:

     

    1. <span style="font-size:18px;">class Apple  
    2. {  
    3.     String name;  
    4.     String color;  
    5.     boolean flag = false;  
    6. }  
    7. class Input implements Runnable  
    8. {  
    9.     private Apple r ;  
    10.     Input(Apple r)  
    11.     {  
    12.         this.r = r;  
    13.     }  
    14.     public void run()  
    15.     {  
    16.         int x = 0;  
    17.         while(true)  
    18.         {  
    19.             synchronized(r)  
    20.             {  
    21.   
    22.                 if(r.flag) //标志位,如果flag=true,那么说明已经有数据,线程等待  
    23.                     try{r.wait();}catch(Exception e){}  
    24.                 if(x==0)  
    25.                 {  
    26.                     r.name="a";  
    27.                     r.color="red";  
    28.                 }  
    29.                 else  
    30.                 {  
    31.                     r.name="b";  
    32.                     r.color = "yellow";  
    33.                 }  
    34.                 x = (x+1)%2;  
    35.                 r.flag = true;//修改标志位  
    36.                 r.notify();//唤醒输出线程  
    37.             }  
    38.         }  
    39.     }  
    40. }  
    41.   
    42. class Output implements Runnable  
    43. {  
    44.     private Apple r ;  
    45.       
    46.     Output(Apple r)  
    47.     {  
    48.         this.r = r;  
    49.     }  
    50.     public void run()  
    51.     {  
    52.         while(true)  
    53.         {  
    54.             synchronized(r)  
    55.             {  
    56.                 if(!r.flag)//如果线程的标志位flag=false,线程等待  
    57.                     try{r.wait();}catch(Exception e){}  
    58.                 System.out.println(r.name+"...."+r.color);  
    59.                 r.flag = false;  
    60.                 r.notify();//唤醒输入线程  
    61.             }  
    62.         }  
    63.     }  
    64. }  
    65. class  InputOutputTest  
    66. {  
    67.     public static void main(String[] args)  
    68.     {  
    69.         Apple r = new Apple();  
    70.   
    71.         Input in = new Input(r);  
    72.         Output out = new Output(r);  
    73.   
    74.         Thread t1 = new Thread(in);  
    75.         Thread t2 = new Thread(out);  
    76.   
    77.         t1.start();  
    78.         t2.start();  
    79.     }  
    80. }</span>  

    总结:

          wait();notify();notifyALL();

          都使用在同步中,因为只有对持有监视器(锁)的线程操作。所以要使用在同步中个,因为只有同步才具有锁

    为什么这些操作线程饿方法要定义Object类中呢?因为这些方法在操作同步线程时,都必须要标识他们所操作的线程只有的锁。只有在同一个锁上的被等待线程,可以被同一个锁notify唤醒。不可以对不同锁中的线程进行唤醒。也就说,等待和唤醒必须是同一个锁。而锁可以使任意对象个,所以可以被任意对象调用的方法定义object类中。

           终止线程只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。特殊情况:当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread类提供该方法 interrupt();

    四、关于run()和start()分析:

    1. <span style="font-size:18px;">class MyThread extends Thread{  
    2.     public void run(){  
    3.         try {  
    4.             Thread.currentThread().sleep(3000);  
    5.         } catch (InterruptedException e) {  
    6.         }  
    7.         System.out.println("MyThread running");  
    8.     }  
    9. }  
    10. public class ThreadTest{  
    11.     public static void main(String argv[]) {  
    12.         MyThread t = new MyThread();  
    13.         t.run();  
    14.         t.start();  
    15.         System.out.println("Thread Test");  
    16.       }  
    17. }</span>  

    总结:

    代码分析过程:MyThread t = new MyThread();创建了一个线程。

    t.run();调用MyThread对象的run方法。这是只有一个线程在运行就是主线程。当主线程执行到了run方法中的sleep(3000);时。这是主线程处于冻结状态。程序并没有任何执行。当3秒过后,主线程打印了  MyThread running。 run方法执行结束。

    t.start();开启了t线程。有两种可能情况。

           第一种,主线程在只执行了t.start()后,还具有执行权,继续往下执行,打印了Thread Test。主线程结束。

    t线程获取执行权,调用自己的run方法。然后执行的sleep(3000);冻结3秒。3秒后,打印MyThread running t线程结束,整个程序结束。

          第二种,主线程执行到t.start();开启了t线程,t线程就直接获取到了执行权。就调用自己的run方法。指定到sleep(3000).t线程冻结3秒,这是t线程就是释放了执行权。那么主线程开始执行打印了Thread Test,主线程结束。

    等到3秒后,t线程打印MyThread running ,然后t线程结束。程序结束。

  • 相关阅读:
    Jmeter响应断言的处理。
    Jmeter超时处理。
    HTTP协议简介以及特点。
    自动化测试面试技巧。
    父类构造方法有无参数对子类的影响。
    自动化分层思想分析1.
    设计模式
    遍历课程列表代码。
    如何遍历当前页课程定位分析,以及代码编写。
    “笨方法”学习Python笔记(1)-Windows下的准备
  • 原文地址:https://www.cnblogs.com/lixiaolun/p/2832751.html
Copyright © 2020-2023  润新知