Java中线程的通信

来源:互联网 发布:离线整个知乎 编辑:程序博客网 时间:2024/06/14 01:23

1.线程的协调运行 

以借助于Object类提供的wait()、notify()和notifyAll()三个方法,这三个方法并不属于Thread类,而是属于Object类。

但这三个方法必须同步监视器对象调用。 
关于这三个方法的解释如下:
 

wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()方法或notifyAll()方法来唤醒该线程。

该wait()方法有三种形式:无时间参数的wait(一直等待,直到其他线程通知),带毫秒参数的wait和带毫秒、微秒参数的wait

(这两种方法都是等待指定时间后自动苏醒)。

调用wait()方法的当前线程会释放对该同步监视器的锁定。
 

notify():唤醒在此同步监视器上等待的单个线程。如果所有线程都在此同步监视器上等待,则会选择唤醒其中一个线程。选择是任意性的。

只有当前线程放弃对该同步监视器的锁定后(使用wait()方法),才可以执行被唤醒的线程。
 

notifyAll():唤醒在此同步监视器上等待的所有线程。只有当前线程放弃对该同步监视器的锁定后,才可以执行被唤醒的线程。

wait与notify方法要注意的事项:
1. wait方法与notify方法是属于Object对象 的。
2. wait方法与notify方法必须要在同步代码块或者是同步函数中才能使用。
3. wait方法与notify方法必需要由同步监视器对象调用。


例如:

package uestc.Thread;//使用wait(),notify()实现经典的生产者与消费者问题。//产品类class Product{String name;   //名字boolean flag = false;   //产品是否生产完毕的标识,默认情况是false}//生产者class Producer extends Thread{Product p;   //产品public Producer(Product p){this.p = p;}public void run(){int i = 0;while(true){synchronized(p){if(p.flag == false){p.name = "苹果";System.out.println("生产者生产出了:"+p.name);p.flag = true;i++;p.notify();}else{//已经生产完毕,等待消费者去消费try {p.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}}}//消费者class Customer extends Thread{Product p;public Customer(Product p){this.p = p;}public void run(){while(true){synchronized(p){if(p.flag == true){      //产品已经生产完毕System.out.println("消费者消费了"+p.name);p.flag = false;p.notify();     //唤醒生产者去生产}else{//产品还没有生产,应该等待生产者去生产try {p.wait();    } catch (InterruptedException e) {e.printStackTrace();}}}}}}public class Demo4 {public static void main(String[] args) {Product p = new Product();    //产品对象//创建生产对象Producer producer = new Producer(p);//创建消费者Customer customer = new Customer(p);//调用start方法开启线程producer.start();customer.start();}}

2. 线程生命周期

任何事物都是生命周期,线程也是,

1. 正常终止  当线程的run()执行完毕,线程死亡。

2. 使用标记停止线程

注意:Stop方法已过时,就不能再使用这个方法。

3. 如果需要停止一个处于等待状态下的线程,那么我们需要通过变量配合notify方法或者interrupt()来使用。

如何使用标记停止线程停止线程。

开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,线程就结束。


3. 后台线程(守护线程)

后台线程:就是隐藏起来一直在默默运行的线程,直到进程结束。

 实现:

       setDaemon(boolean on) 例如:d.setDaemon(true); //setDaemon() 设置d线程是否为守护线程,true为守护线程, false为非守护线程

特点:

当所有的非后台线程结束时,程序也就终止了同时还会杀死进程中的所有后台线程,也就是说,只要有非后台线程还在运行,程序就不会终止,执行main方法的主线程就是一个非后台线程。

必须在启动线程之前(调用start方法之前)调用setDaemon(true)方法,才可以把该线程设置为后台线程。 

可以使用isDaemon() 测试该线程是否为后台线程(守护线程)。 例如:System.out.println("是守护线程吗?"+ d.isDaemon()); //判断线程是否为守护线程。


4.Thread的join方法


当A线程执行到了B线程Join方法时A就会等待,等B线程都执行完A才会执行,Join可以用来临时加入线程执行。

join()方法通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。

当所有的小问题都得到处理后,再调用主线程来进一步操作


0 0
原创粉丝点击