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

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

猜你喜欢

转载自blog.csdn.net/fuyuwei2015/article/details/85016274