Java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍

举报
af913337456 发表于 2018/11/30 15:43:44 2018/11/30
【摘要】 (原创,转载请说明出处!谢谢--http://www.cnblogs.com/linguanh/) 此文目的为了帮助大家较全面、通俗地了解线程 Thread 相关基础知识! 目录: --线程的创建: --启动线程 --线程的调度 --Thread 类的简介 --线程的同步/异步 --wait() 和 notify(),...

(原创,转载请说明出处!谢谢--http://www.cnblogs.com/linguanh/)

 

 此文目的为了帮助大家较全面、通俗地了解线程 Thread 相关基础知识!

 

目录:

       --线程的创建:

       --启动线程

       --线程的调度

       --Thread 类的简介

       --线程的同步/异步

       --wait() 和 notify(),notifyAll()方法

     

在讲线程之前,先说下进程。

 

进程:是运行系统中,每个独立运行的程序。例如win7,我既用酷狗软件听歌,又玩 LOL 游戏,又上QQ,那么这就有3个进程。

线程:一个进程里面有很多线程,进程是由线程组成的,线程的结束不一定会导致进程结束,而一个进程的结束,则会连带它里面的所有线程被结束。

 

------------线程的创建:

创建->

        java 中有两种方式:

        1,一种是通过实现Runnable 接口

        2,另一种是继承线程类 Thread

实现Runnable接口的实例代码:

1 class threadT implements Runnable{2     @Override3     public void run() {4         //在这编辑要执行的代码5     }6 }

上述代码,通过实现 Runnable 的接口,重写接口函数 run() 来实现新建一个线程。类比,点击事件的接口 OnClickListener

 

实现:

1 Thread thread_test = new Thread(new threadT);2  //实例化代码一般放在主线程中,例如 main 中 或 onCreate()

 

继承线程类Thread 的实例代码:

1 class threadT1 extends Thread{2         public void run(){3          // edit your code4         }5  }

 

实现:

 Thread thread_test =  ThreadT1();
  thread_test.start();

 

上述两种方法的比较:

      本人建议使用第一种,即使用实现Runnable 接口的方法来新建线程。

      原因:

            1:避免java 的单一 继承带来的局限;

            2:和 onClickListener 点击事件一样,当你有多个线程时,使用Runnable 再在run内用一个 switch 就能分开使用;

 

--------------启动线程:

线程的启动一般都是通过方法执行 statrt() 进行的。

 

完整 main 函数测试代码:

 1 package com.LGH.ew; 2  3 /** 4  *  Created by Administrator on 2015/4/25. 5  *  各线程,当主线程main 执行完了,它们还会继续执行,彼此不影响 6  *  多线程卖票 显示 demo,by LinGuanHong 7  */ 8 public class threadTest { 9     public static void main(String[] args){10         threadT t1 = new threadT1();//线程 111         Thread t2 = new Thread(new ThreadT());//线程 212        13         t2.start();14         t1.start();15     }16 }

 

------------线程的调度:

调度是什么意思呢?就是 cpu 执行每个线程的顺序,注意,不一定是按顺序的,这个和线程的优先级有关!

线程的调用是统一由JVM根据时间片来调度的,其执行顺序随机。大致执行流程如下:

 

 

由上述可以看出, jvm 在执行多线程 程序的时候,在某一个时间段,其实也是只能运行一个线程,

但是它用划分时间片段的机制来转换调用各个线程,这个时间片段很短!

 

-----------Thread 类的简介

 

java.lang.Thread 类:

    常用的方法有:

    ---public void start(); 启动该线程,其中调用了这个方法不一定就立即进行,还要看是否被调度到;

    ---public static Thread currentThread(); 静态方法,这个方法很重要,用来返回当前正在执行的线程对象引用;

    ---public final booleann isAlive();测试线程是否还活着;

    ---public Thread.State getState();返回该线程当前的状态,

                 分别有:

                          NEW 实例化了,但尚未启动的线程是这种状态,新建 态;

                          RUNNABLE 正在被执行的状态;

                          BLOCKED 受阻塞并等待某个监视器锁的线程态;

                          WAITING 无限期地等待另外一个线程来执行特地操作,等待 态;

                          TIMED_WAITING 等待另一个线程来执行取决于指定等待时间的操作,超时等待 态

                          TERMINATED 已退出的线程的状态,终止 态。

     ---public final String getName();返回线程名称,一般和setName(),连用;

     ---public final void setDaemon(boolean on);将该线程标记为守护线程;

     ---public static void sleep(long millis);在指定的毫秒内,让该线程暂停;

     ---public final void setPriority(int level);设置线程的优先级,可以是 1,5,10,分别是 低、普通、最高,默认是 5 ;

     ---public static void yield();线程让步,它会暂停该线程,把执行的机会让给相同或优先级更高的线程;

     ---public void final join();把某线程加入到某线程中去,被加者变为子线程;

     ---public void interrupt(); 中断线程.

 

------------线程的生命周期

 

其生命周期可以总结为上面的 6个 状态,图解如下:

 

-------------线程的同步/异步

下面通过demo 代码说明,内涵 synchronized 保护机制

 

  1 package com.LGH.ew;  2   3 /**  4  *  Created by Administrator on 2015/4/25.  5  *  各线程,当主线程main 执行完了,它们还会继续执行,彼此不影响  6  *  多线程卖票 显示 demo,by LinGuanHong  7  */  8 public class threadTest { //卖火车票例子  9     public static void main(String[] args){ 10         threadT T = new threadT(); 11         Thread t1 = new Thread(T);//线程 1 12         t1.setName("1");// 设置 线程名字 13         //t1.getState(); 这里有具体的线程对象,所以可以直接使用其类方法; 14         t1.start(); 15         Thread t2 = new Thread(T);//线程 2 16         t2.setName("2"); 17         t2.start(); 18         Thread t3 = new Thread(T);//线程 3 19         t3.setName("3"); 20         t3.start(); 21         Thread t4 = new Thread(T);//线程 4 22         t4.setName("4"); 23         t4.start(); 24         Thread t5 = new Thread(T);//线程 5 25         t5.setName("5"); 26         t5.start(); 27     } 28 } 29 class threadT implements Runnable{ //实例化接口  30     private int tickets = 0; 31     @Override 32     public void run() { 33         boolean control = true; 34         while(control){ 35             control = sell();//调用sell 方法,大家可以通过改变这个函数的调用,来看异步、同步的效果 36         } 37     } 38  39     public boolean sell(){//异步线程机制,会被打断,所谓打断,就是会出现 线程1 卖了第2张票时,线程3也卖了第2 张 40         boolean control = true ; 41         if(tickets<100){ 42             tickets ++; 43             //在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法 44             System.out.println(Thread.currentThread().getName()+":"+tickets);//同上 45             Thread.State state = Thread.currentThread().getState();//同上 46             System.out.println("State:"+state.toString());//输出当前的状态,正常是 runnable 47         }else{ 48             control = false; 49         } 50         try{ 51             Thread.sleep(1); 52         }catch (Exception e){ 53             e.printStackTrace(); 54         } 55         return control; 56     } 57  58     //关键字 - synchronized 保护 当前 函数在执行时不被其他线程打断,同步线程机制 59     //整体同步,效率低 60     public synchronized boolean sell1(){ 
 61         boolean control = true ; 62         if(tickets<100){ 63             tickets ++; 64             //在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法 65             System.out.println(Thread.currentThread().getName()+":"+tickets);//同上 66             Thread.State state = Thread.currentThread().getState();//同上 67            // System.out.println("State:"+state.toString()); 68         }else{ 69             control = false; 70         } 71         try{ 72             Thread.sleep(1); 73         }catch (Exception e){ 74             e.printStackTrace(); 75         } 76         return control; 77     } 78     //关键字 - synchronized 实质是一个对象锁 79  80     public boolean sell2(){ // 条件 关键字 - synchronized 保护 当前 函数在执行时不被其他线程打断,同步线程机制 81         boolean control = true ; 82         synchronized(this) { //仅仅同步会操作到的共同部分变量,tickets,这样避免同步整体,提高效率 83             if (tickets < 100) { 84                 tickets++; 85                 //在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法 86                 System.out.println(Thread.currentThread().getName() + ":" + tickets);//同上 87                 Thread.State state = Thread.currentThread().getState();//同上 88                 // System.out.println("State:"+state.toString()); 89             } else { 90                 control = false; 91             } 92         } 93         try{ 94             Thread.sleep(1); 95         }catch (Exception e){ 96             e.printStackTrace(); 97         } 98         return control; 99     }100 }

 

-------------wait() 和 notify(),notifyAll()方法


他们是同步机制中的重要部分,必须和 synchronized 关键字结合使用,即在 synchronized 代码块中使用!

否在 抛出 Illegal..... 非法异常。

wait() 被调用,当前线程将会被中断运行,并且放弃该对象的锁;

执行了 notify() 后,会唤醒此对象等待池中的某个线程,使之成为可运行的线程;

notifyAll()则唤醒所有;

 

下面用一个具体的demo 说明:

前言-------------

     生产者和消费者的问题,生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定的产品,如果生产者生产过多了的产品,店员会叫生产者等一下,如果店中有空位放产品了再通知生产者继续生产;

     如果店中供不应求,店员会叫消费者等一会,等生产者生产了再叫消费者来拿。

问题:

      生产者生产过快,消费者会漏掉一些,没取到;

      消费者比生产者快,消费者会拿到相同的;

 

 1 package com.LGH.ew.view; 2  3 /** 4  * Created by Administrator on 2015/4/25. 5  */ 6 public class Product { //生产者、消费者问题 7     public static void main(String[] args){ 8         clerk c = new clerk(); 9         Thread productT = new Thread(new Producer(c));//生产者线程10         Thread consumerT = new Thread(new Consumer(c));//消费者线程11         productT.start();12         consumerT.start();13     }14 }15 class clerk{ //店员16     private int product = 0; //默认 0 个产品17     public synchronized void addproduct(){ //生产出的产品,交给店员18         if(this.product>=20){19             try{20                 wait(); //产品过多,稍后再生产21             }catch (Exception e){22                 e.printStackTrace();23             }24         }else{25             product++;26             System.out.println("生产者生产第"+product+"个产品。");27             notifyAll(); //通知等待区的消费者可取产品28         }29     }30     public synchronized void getproduct(){ //消费者从店员处取产品31         if(this.product<=0){32             try{33                 wait(); //缺货,稍后再取34             }catch (Exception e){35                 e.printStackTrace();36             }37         }else{38             System.out.println("消费者取走了第:" + product + "产品。");39             product--;40             notifyAll(); //通知等待取得生产者可以继续生产41         }42     }43 }44 45 class Producer implements Runnable{ //生产者线程46 47     private clerk c;48     public Producer(clerk c){49         this.c = c;50     }51     @Override52     public void run() {53         System.out.println("生产者开始生产产品。");54         while(true){55             try{56                 Thread.sleep((int)(Math.random()*10)*100);57             }catch(Exception e){58                 e.printStackTrace();59             }60             c.addproduct(); //生产61         }62     }63 }64 65 class Consumer implements Runnable{ //消费者线程66 67     private clerk c ;68 69     public Consumer(clerk c){70         this.c = c;71     }72     @Override73     public void run() {74         System.out.println("消费者开始取走产品。");75         while(true){76             try{77                 Thread.sleep((int)(Math.random()*10)*100);78             }catch(Exception e){79                 e.printStackTrace();80             }81             c.getproduct(); //取产品82         }83     }84 }

 

全文终,各位如果觉得还可以的话,请帮忙点个赞,让更多人能看到。谢谢

 

spacer.gif


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。