多线程复习笔记之二【线程间的通信】

Object.wait:释放锁,当时代码不会往下继续执行,需要等待notify通知,wait(1000)超过1秒自动唤醒

Object.notify:不释放锁,需要等到同步代码块执行完毕,如果没有wait线程,notify命令将被忽略。

condition

如果有多个线程处于等待状态,我想唤醒指定的一个线程,Object.notify是唤醒随机一个是无法实现的。condition实现过程如下:

ReentrantLock lock = new ReentrantLock(true);
Condition aCondition = reentrantLock.newCondition();
Condition cCondition = reentrantLock.newCondition();
//线程A:
{
    lock.lock();
    aCondition.await();	//此时当前线程释放lock锁,进入[等待状态],等待其他线程执行aCondition.signal()时才有可能执行
    A do something
    lock.unlock();
}

//线程C:

{
    lock.lock();
    cCondition.await();
    do something
    lock.unlock();
}
//线程B:
{
    lock.lock();
    aCondition.signal();	//此时当前线程释放lock锁,随机唤醒一个处于等待状态等待aCondition的线程,继续执行await后面的程序。
    //cCondition.signal();	此时当前线程释放lock锁,随机唤醒一个处于等待状态等待cCondition的线程,继续执行await后面的程序。
    lock.unlock();
}

condition在唤醒的时候可以指定唤醒哪个锁下的线程。

【使用线程间的通信实现生产者消费者】

【生产者】

package com.fyw.thread;

public class Producer {

	private String lock;

	public Producer(String lock) {
		super();
		this.lock = lock;
	}
	
	public void produce(){
		try {
			synchronized (lock) {
				if(!ValueObject.value.equals("")){
					lock.wait();
				}
				ValueObject.value = String.valueOf(System.currentTimeMillis())+System.nanoTime();
				System.out.println("生产:"+ValueObject.value);
				lock.notify();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

package com.fyw.thread;

public class ThreadProduce extends Thread {
	
	private Producer p ;
	
	public ThreadProduce(Producer p) {
		super();
		this.p = p;
	}

	@Override
	public void run() {
		for(;;){
			p.produce();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	
}

【消费者】

package com.fyw.thread;

public class Consumer {

	private String lock;

	public Consumer(String lock) {
		super();
		this.lock = lock;
	}
	
	public void consume(){
		try {
			synchronized (lock) {
				if(ValueObject.value.equals("")){
					lock.wait();
				}
				System.out.println("消费:"+ValueObject.value);
				// 消费
				ValueObject.value="";
				lock.notify();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}

package com.fyw.thread;

public class ThreadConsumer extends Thread {

	private Consumer c;

	public ThreadConsumer(Consumer c) {
		super();
		this.c = c;
	}

	@Override
	public void run() {
		for(;;){
			c.consume();
		}
	}
	
	
}

【启动】

package com.fyw.thread;

public class PCTest {

	public static void main(String[] args) {
		String lock = new String("lock");
		Producer p = new Producer(lock);
		Consumer c = new Consumer(lock);
		ThreadProduce tp = new ThreadProduce(p);
		ThreadConsumer tc = new ThreadConsumer(c);
		tp.start();
		tc.start();
	}
}

【输出】

生产:154462818466096495898923525
消费:154462818466096495898923525
生产:154462818566096496899278715
消费:154462818566096496899278715
生产:154462818666196497899629894
消费:154462818666196497899629894
生产:154462818766196498900164868
消费:154462818766196498900164868
生产:154462818866296499901082747
消费:154462818866296499901082747
生产:154462818966396500901689196
消费:154462818966396500901689196
生产:154462819066396501901767236
消费:154462819066396501901767236
生产:154462819166396502901990051
消费:154462819166396502901990051
生产:154462819266396503902137378
消费:154462819266396503902137378

【实现长度为1的阻塞队列】

【出队列与入队列】

package com.fyw.thread.queue;

import java.util.ArrayList;
import java.util.List;

public class MyBlockQueue {

	private List<String> list = new ArrayList<>();
	
	synchronized public void push(){
		try {
			if(this.list.size() == 1){
				this.wait();
			}
			list.add("object"+Math.random());
			this.notify();
			System.out.println("push list size is "+list.size());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	synchronized public String pop(){
		String popValue = "";
		try {
			if(this.list.size() == 0){
				this.wait();
			}
			popValue = " "+list.get(0);
			System.out.println("the popValue is:"+popValue);
			list.remove(0);
			this.notify();
			System.out.println("pop list size is "+list.size());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return popValue;
	}
}

【循环入队】

package com.fyw.thread.queue;

public class PushThread extends Thread {

	private MyBlockQueue stack;

	public PushThread(MyBlockQueue stack) {
		super();
		this.stack = stack;
	}

	@Override
	public void run() {
		for(;;){
			stack.push();
		}
	}
	
	
}

【循环出队】

package com.fyw.thread.queue;

public class PopThread extends Thread {

	private MyBlockQueue stack;

	public PopThread(MyBlockQueue stack) {
		super();
		this.stack = stack;
	}

	@Override
	public void run() {
		for(;;){
			stack.pop();
		}
	}
	
	
}

【测试】

package com.fyw.thread.queue;

public class TestQueue {

	public static void main(String[] args) {
		MyBlockQueue stack = new MyBlockQueue();
		PushThread push = new PushThread(stack);
		PopThread pop = new PopThread(stack);
		
		push.start();
		pop.start();
	}

}

【输出】

push list size is 1
the popValue is: object0.6381141020856054
pop list size is 0
push list size is 1
the popValue is: object0.7736294633434665
pop list size is 0
push list size is 1
the popValue is: object0.2567516689810333
pop list size is 0
push list size is 1
the popValue is: object0.024418178034380067
pop list size is 0
push list size is 1
the popValue is: object0.6143726198167988
pop list size is 0
push list size is 1
the popValue is: object0.49025399739088094
pop list size is 0
push list size is 1
the popValue is: object0.8784830759986317
pop list size is 0

上面的是1对1的生产者消费者模型,如果是1对多或者多对多,list.size需要使用while判断,否则当其他线程修改size值对当前线程无感知,导致条件判断错误,然后notify改成notifyAll防止出现线程假死状态。

【使用wait和notify实现交叉执行示例】

package com.fyw.thread.queue;

public class DBTools {
	
	private volatile boolean isTurn = false;

	synchronized public void bakupA(){
		try {
			while(this.isTurn){
				this.wait();
			}
			for(int i=0;i<5;i++){
				System.out.println("AAAAAA");
			}
			this.isTurn = true;
			this.notifyAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	synchronized public void bakupB(){
		try {
			while(!this.isTurn){
				this.wait();
			}
			for(int i=0;i<5;i++){
				System.out.println("BBBBBB");
			}
			this.isTurn = false;
			this.notifyAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

package com.fyw.thread.queue;

public class PopThread extends Thread {

	private DBTools db;

	public PopThread(DBTools db) {
		super();
		this.db = db;
	}

	@Override
	public void run() {
		db.bakupA();
	}

	
}

package com.fyw.thread.queue;

public class PushThread extends Thread {
	
	private DBTools db;

	public PushThread(DBTools db) {
		super();
		this.db = db;
	}

	@Override
	public void run() {
		db.bakupB();
	}
	
	
}

package com.fyw.thread.queue;

public class TestQueue {

	public static void main(String[] args) {
		DBTools stack = new DBTools();
		
		for(int i=0;i<20;i++){
			PushThread push = new PushThread(stack);
			push.start();
			PopThread pop = new PopThread(stack);
			pop.start();
		}
		
	}

}

【运行结果如下】

AAAAAA
AAAAAA
AAAAAA
AAAAAA
AAAAAA
BBBBBB
BBBBBB
BBBBBB
BBBBBB
BBBBBB
AAAAAA
AAAAAA
AAAAAA
AAAAAA
AAAAAA
BBBBBB
BBBBBB
BBBBBB
BBBBBB
BBBBBB
AAAAAA
AAAAAA
AAAAAA
AAAAAA
AAAAAA
BBBBBB
BBBBBB
BBBBBB
BBBBBB
BBBBBB

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值