关闭

Java中线程的通信

标签: javajava基础线程进程
201人阅读 评论(0) 收藏 举报
分类:

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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6145次
    • 积分:234
    • 等级:
    • 排名:千里之外
    • 原创:17篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2条
    文章分类
    文章存档
    最新评论