Java多线程(四)线程间通信 wait notify 7.29

等待/通知机制

不使用等待/通知机制实现线程间通信

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

public class MyList {
	private List list = new ArrayList();
	public void add() {
		list.add("gaogagao");
	}
	public int size() {
		return list.size();
	}
}

public class Test {
	public static void main(String[] args) {
		MyList service = new MyList();
		ThreadA ta = new ThreadA(service);
		ta.setName("A");
		ta.start();
		ThreadB tb = new ThreadB(service);
		tb.setName("B");
		tb.start();
	}
}

public class ThreadA extends Thread{
	private MyList list;
	public ThreadA(MyList list) {
		super();
		this.list = list;
	}
	public void run() {
		try {
			for (int i = 0; i < 10; i++) {
				list.add();
				System.out.println("添加了" + (i + 1) + " 个元素 ");
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class ThreadB extends Thread{
	private MyList list;
	public ThreadB(MyList list) {
		super();
		this.list = list;
	}

	public void run() {
		try {
			while (true) {
				if (list.size() == 5) {
					System.out.println("==5了,线程b要退出了!");
					throw new InterruptedException();
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

等待/通知机制的实现

public class Test1 {
	public static void main(String[] args) {
		try {
			String newString = new String("");
			newString.wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

public class Test2 {
	public static void main(String[] args) {
		try {
			String lock = new String();
			System.out.println("syn上面");
			synchronized (lock) {
				System.out.println("syn第一行");
				lock.wait();
				System.out.println("wait下的代码");
			}
			System.out.println("syn下面的代码");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class TestAB {
	public static void main(String[] args) {
		try {
			Object lock = new Object();
			ThreadA ta = new ThreadA(lock);
			ta.start();
			Thread.sleep(1000);
			ThreadB tb = new ThreadB(lock);
			tb.start();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class ThreadA extends Thread{
	private Object lock;
	public ThreadA(Object lock) {
		super();
		this.lock = lock;
	}
	
	public void run() {
		try {
			synchronized (lock) {
				System.out.println(" start  wait time = " + System.currentTimeMillis());
				lock.wait();
				System.out.println(" stop  wait time = " + System.currentTimeMillis());
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class ThreadB extends Thread{
	private Object lock;
	public ThreadB(Object lock) {
		super();
		this.lock = lock;
	}
	public void run() {
		synchronized (lock) {
			System.out.println(" start notify time = " + System.currentTimeMillis());
			lock.notify();
			System.out.println(" stop notify time = " + System.currentTimeMillis());
		}
	}
}

wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒;

notify()方法可以随机唤醒等待队列中等待同一共享资源的“一个”线程,并使该线程退出等待队列,进入可运行状态;

notifyAll()方法可以使所有正在等待队列中等待同一共享资源的“全部”线程从等待状态退出,进入可运行状态;

 

wait()锁释放;notify()锁不释放

public class Service {
	public void testMethod(Object lock) {
		try {	
			synchronized (lock) {
				System.out.println("begin wait()");
				lock.wait();
				System.out.println("  end wait()");
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

public class TestAB {
	public static void main(String[] args) {
		Object lock = new Object();
		ThreadA ta = new ThreadA(lock);
		ta.start();
		ThreadB tb = new ThreadB(lock);
		tb.start();
	}
}
public class ThreadA extends Thread{
	private Object lock;
	public ThreadA(Object lock) {
		super();
		this.lock = lock;
	}
	public void run() {
		Service service = new Service();
		service.testMethod(lock);
	}
}
public class ThreadB extends Thread{
	private Object lock;
	public ThreadB(Object lock) {
		super();
		this.lock = lock;
	}
	public void run() {
		Service service = new Service();
		service.testMethod(lock);
	}
}

 

当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException异常;

方法wait(long)的使用:

带一个参数的wait(long)方法的功能时等待某一段时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒;

其他

通知过早:如果通知过早,则会打乱程序正常的运行逻辑;

等待wait的条件发生彪悍:wait等待的条件发生了变化,也容易造成程序逻辑的混乱;

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

public class ValueObject {
	public static List list = new ArrayList();
}
public class Add {
	private String lock;
	public Add(String lock) {
		super();
		this.lock = lock;
	}
	public void add() {
		synchronized(lock) {
			ValueObject.list.add("anyString");
			lock.notifyAll();
		}
	}
}

public class Subtract {
	private String lock;
	public Subtract (String lock) {
		super();
		this.lock = lock;
	}
	public void subtract() {
		try {
			synchronized (lock) {
				while(ValueObject.list.size() == 0) {
					System.out.println(" wait begin ThreadName = "
							+ Thread.currentThread().getName());
					lock.wait();
					System.out.println(" wait  end  ThreadName = "
							+ Thread.currentThread().getName());
				}
				ValueObject.list.remove(0);
				System.out.println("list size = " + ValueObject.list.size());
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class ThreadAdd extends Thread{
	private Add p;
	public ThreadAdd(Add p) {
		super();
		this.p = p;
	}
	public void run() {
		p.add();
	}
}
public class ThreadSubtract extends Thread{
	private Subtract r;
	public ThreadSubtract(Subtract r) {
		super();
		this.r = r;
	}
	public void run() {
		r.subtract();
	}
}

import com.highgo.t9_WaitOld.*;

public class Run {
	public static void main(String[] args) throws InterruptedException {
		String lock = new String("");
		Add add = new Add(lock);
		Subtract subtract = new Subtract(lock);
		ThreadSubtract subtractT1 = new ThreadSubtract(subtract);
		subtractT1.setName("subtarctT1");
		subtractT1.start();
		ThreadSubtract subtractT2 = new ThreadSubtract(subtract);
		subtractT2.setName("subtarctT2");
		subtractT2.start();
		Thread.sleep(1000);
		ThreadAdd addThread = new ThreadAdd(add);
		addThread.setName("addThread");
		addThread.start();
	}
}


生产者/消费者模式的实现:

一生产与一消费:

多生产与多消费:

操作值,操作栈,假死问题

//消费者
public class C {
	private String lock;
	public C(String lock) {
		super();
		this.lock = lock;
	}
	public void getValue() {
		try {
			synchronized(lock) {
				while(ValueObject.value.equals("")) {
					System.out.println("消费者" 
							+ Thread.currentThread().getName() + "* WAITING了");
					lock.wait();
				}
				System.out.println("消费者"
						+ Thread.currentThread().getName() + " RUNNABLE了");
				System.out.println("get的值是 " + ValueObject.value);
				ValueObject.value = "";
				lock.notifyAll();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

//生产者
public class P {
	private String lock;
	public P(String lock) {
		super();
		this.lock = lock;
	}
	public void setValue() {
		try {
			synchronized (lock) {
				while(!ValueObject.value.equals("")) {
					System.out.println("生产者"
					+ Thread.currentThread().getName() + " WAITING了 * * *");
					lock.wait();
				}
				System.out.println("生产者"
						+ Thread.currentThread().getName() + " RUNNABLE了 ");
				String value = System.currentTimeMillis() + "_" + System.nanoTime();
				System.out.println("set的值是 " + value);
				ValueObject.value = value;
				lock.notifyAll();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

public class ThreadP extends Thread{
	private P p;
	public ThreadP(P p) {
		super();
		this.p = p;
	}
	public void run() {
		while(true) {
			p.setValue();
		}
	}
}
public class ThreadC extends Thread{
	private C r;
	public ThreadC(C r) {
		super();
		this.r = r;
	}
	public void run() {
		while(true) {
			r.getValue();
		}
	}
}
public class ValueObject {
	public static String value = "";
}

//解决假死的方法,将P.java 和 C.java 文件中的notify()改为notifyAll(),
//它的原理就是不光通知同类线程也包括异类线程;

public class Run {
	public static void main(String[] args) throws InterruptedException {
		String lock = new String("");
		P p = new P(lock);
		C r = new C(lock);
		ThreadP[] pThread = new ThreadP[2];
		ThreadC[] rThread = new ThreadC[2];
		for (int i = 0; i < 2; i++) {
			pThread[i] = new ThreadP(p);
			pThread[i].setName("生产者" + (i + 1));
			rThread[i] = new ThreadC(r);
			rThread[i].setName("消费者" + (i + 1));
			pThread[i].start();
			rThread[i].start();
		}
		Thread.sleep(5000);
		Thread[] threadArray = 
				new Thread[Thread.currentThread().getThreadGroup().activeCount()];
		Thread.currentThread().getThreadGroup().enumerate(threadArray);
		for (int i = 0; i < threadArray.length; i++) {
			System.out.println(threadArray[i].getName() + " " + threadArray[i].getState());
		}
	}
}





通过管道进行线程间通信:字节流/字符流

import java.io.IOException;
import java.io.PipedOutputStream;

public class WriteData {
	public void writeMethod(PipedOutputStream out) {
		try {
			System.out.println("write : ");
			for(int i = 0; i < 300; i++) {
				String outData = "" + (i + 1);
				out.write(outData.getBytes());
				System.out.print(outData);
			}
			System.out.println();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

import java.io.IOException;
import java.io.PipedInputStream;

public class ReadData {
	public void readMethod(PipedInputStream input) {
		try {
			System.out.println("read : ");
			byte[] byteArray = new byte[20];
			int readLength = input.read(byteArray);
			while(readLength != -1) {
				String newData = new String(byteArray, 0, readLength);
				System.out.print(newData);
				readLength = input.read(byteArray);
			}
			System.out.println();
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
import java.io.PipedInputStream;

public class ThreadR extends Thread{
	private ReadData read;
	private PipedInputStream input;
	public ThreadR(ReadData read, PipedInputStream input) {
		super();
		this.read = read;
		this.input = input;
	}
	public void run() {
		read.readMethod(input);
	}
}
import java.io.PipedOutputStream;

public class ThreadW extends Thread{
	private WriteData write;
	private PipedOutputStream out;
	public ThreadW(WriteData write, PipedOutputStream out) {
		super();
		this.write = write;
		this.out = out;
	}
	public void run() {
		write.writeMethod(out);
	}
}
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Run {
	public static void main(String[] args) {
		try {
			WriteData writeData = new WriteData();
			ReadData readData = new ReadData();
			
			PipedInputStream inputStream = new PipedInputStream();
			PipedOutputStream outputStream = new PipedOutputStream();
			
			outputStream.connect(inputStream);
			
			ThreadR threadR= new ThreadR(readData, inputStream);
			threadR.start();
			
			Thread.sleep(2000);
			
			ThreadW threadW= new ThreadW(writeData, outputStream);
			threadW.start();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

等待/通知之交叉备份:

public class BackupA extends Thread{
	private DBTools dbtools;
	public BackupA(DBTools dbtools) {
		super();
		this.dbtools = dbtools;
	}
	public void run() {
		dbtools.backupA();
	}
}
public class BackupB extends Thread{
	private DBTools dbtools;
	public BackupB(DBTools dbtools) {
		super();
		this.dbtools = dbtools;
	}
	public void run() {
		dbtools.backupB();
	}
}

public class DBTools {
	volatile private boolean prevIsA = false;
	synchronized public void backupA() {
		try {
			while(prevIsA == true) {
				wait();
			}
			for (int i = 0; i < 5; i++ ) {
				System.out.println("*****");
			}
			prevIsA = true;
			notifyAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	synchronized public void backupB() {
		try {
			while(prevIsA == false) {
				wait();
			}
			for (int i = 0; i < 5; i++ ) {
				System.out.println("+++++");
			}
			prevIsA = false;
			notifyAll();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class Run {
	public static void main(String[] args) {
		DBTools dbtools = new DBTools();
		for (int i = 0; i < 10; i++) {
			BackupB output = new BackupB(dbtools);
			output.start();
			BackupA input = new BackupA(dbtools);
			input.start();
		}
	}
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值