Java多线程编程(线程间通信)

方法wait的作用是使当前执行代码的线程进行等待,将当前线程置入预执行队列,在调用wait之前,线程必须获得该对象的对象级别锁,即只能在同步方法或者同步块中调用wait方法。

方法notify也要在同步方法或同步块中调用,

再执行notify方法后,要等到执行notify的方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁。

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Object lock = new Object();
		MyThreadA a = new MyThreadA(lock);
		a.start();
		Thread.sleep(3000);
		MyThreadB b = new MyThreadB(lock);
		b.start();

	}
}

package com.java.mul;

public class MyThreadA extends Thread{
	private Object lock;
	public MyThreadA(Object lock) {
		super();
		this.lock = lock;
	}
	
	@Override
	public void run() {
		
		try {
			synchronized(lock) {
				System.out.println("start " + System.currentTimeMillis());
				lock.wait();
				System.out.println("finish " + System.currentTimeMillis());
			}

			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private Object lock;
	public MyThreadB(Object lock) {
		super();
		this.lock = lock;
	}
	
	@Override
	public void run() {
		
			synchronized(lock) {
				System.out.println("start notify " + System.currentTimeMillis());
				lock.notify();
				System.out.println("finish notify" + System.currentTimeMillis());
			}

	}
}

package com.java.mul;

import com.java.mul.extthread.Alogin;
import com.java.mul.extthread.BLogin;

public class multest {

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Object lock = new Object();
		MyThreadA a = new MyThreadA(lock);
		a.start();
		Thread.sleep(50);
		MyThreadB b = new MyThreadB(lock);
		b.start();

	}
}

package com.java.mul;

public class MyThreadA extends Thread{
	private Object lock;
	public MyThreadA(Object lock) {
		super();
		this.lock = lock;
	}
	
	@Override
	public void run() {
		
		try {
			synchronized(lock) {
				if(MyList.size() != 5) {
					System.out.println("start " + System.currentTimeMillis());
					lock.wait();
					System.out.println("finish " + System.currentTimeMillis());
				}
				
			}

			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

public class MyThreadB extends Thread{
	private Object lock;
	public MyThreadB(Object lock) {
		super();
		this.lock = lock;
	}
	
	@Override
	public void run() {
				try {
					synchronized(lock) {
						for(int i = 0;i<10;i++) {
							MyList.add();
							if(MyList.size() == 5) {
								lock.notify();
								System.out.println("send notyfy ");
							}
							System.out.println("add  " + (i + 1)+"elements");
						}
					Thread.sleep(1000);
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			

	}
}

package com.java.mul;

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

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

生产者消费者

package com.java.mul;

public class P {
	private String lock;
	public P(String lock) {
		super();
		this.lock = lock;
	}
	public void setValue() {
		try {
			synchronized(lock) {
				if(!ValueObject.value.equals("")) {
					lock.wait();
				}
				String value = System.currentTimeMillis() + "_" + System.nanoTime();
				System.out.println("set is " + value);
				ValueObject.value = value;
				lock.notify();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

package com.java.mul;

public class C {
	private String lock;
	public C(String lock) {
		super();
		this.lock = lock;
	}
	public void getValue() {
		try {
			synchronized(lock) {
				if(ValueObject.value.equals("")) {
					lock.wait();
				}

				System.out.println("get is " + ValueObject.value);
				ValueObject.value = "";
				lock.notify();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

package com.java.mul;

public class ValueObject {
	public static String value = "";

}

package com.java.mul;

public class ThreadP extends Thread{
	private P p;
	public ThreadP(P p) {
		super();
		this.p = p;
	}
	
	@Override
	public void run() {
		while(true) {
			p.setValue();
		}
	}
}

package com.java.mul;

public class ThreadC  extends Thread{
	private C c;
	public ThreadC(C c) {
		super();
		this.c = c;
	}
	
	@Override
	public void run() {
		while(true) {
			c.getValue();
		}
	}
}

package com.java.mul;

public class Run {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String lock = new String("");
		P p = new P(lock);
		C c = new C(lock);
		ThreadP pThread = new ThreadP(p);
		ThreadC cThread = new ThreadC(c);
		pThread.start();
		cThread.start();
	}

}

当有多个生产者和消费者,生产者的notify有可能唤醒生产者,这样积少成多,容易造成假死。

一生产一消费

package com.java.mul;

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

public class MyStack {
	private List list = new ArrayList();
	synchronized public void push() {
		try {
			if(list.size() == 1) {
				this.wait();
			}
			list.add("anyString=" + Math.random());
			this.notify();
			System.out.println("push=" + list.size());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	synchronized public String pop() {
		String returnValue = "";
		try {
			if(list.size()==0) {
				System.out.println("pop:"+ Thread.currentThread().getName() + " wait");
				this.wait();
			}
			returnValue = "" + list.get(0);
			list.remove(0);
			this.notify();
			System.out.println("pop="+list.size());
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnValue;
	}
}

package com.java.mul;

public class ThreadC  extends Thread{
	private C c;
	public ThreadC(C c) {
		super();
		this.c = c;
	}
	
	@Override
	public void run() {
		while(true) {
			c.popService();
		}
	}
}

package com.java.mul;

public class ThreadP extends Thread{
	private P p;
	public ThreadP(P p) {
		super();
		this.p = p;
	}
	
	@Override
	public void run() {
		while(true) {
			p.pushService();
		}
	}
}

package com.java.mul;

public class P {
	private MyStack myStack;
	public P(MyStack myStack) {
		super();
		this.myStack = myStack;
	}
	public void pushService() {
		myStack.push();
	}


}

package com.java.mul;

public class C {
	private MyStack myStack;
	public C(MyStack myStack) {
		super();
		this.myStack = myStack;
	}

	public void popService() {
		System.out.println("pop=" + myStack.pop());
	}

}

package com.java.mul;

public class Run {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyStack myStack = new MyStack();
		P p = new P(myStack);
		C c = new C(myStack);
		ThreadP pThread = new ThreadP(p);
		ThreadC cThread = new ThreadC(c);
		pThread.start();
		cThread.start();
	}

}

一生产多消费(要把if换成while,来防止一个pop被唤醒,但是listsize为0,但是这时候也可能会发生假死)

package com.java.mul;

public class Run {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyStack myStack = new MyStack();
		P p = new P(myStack);
		C c1 = new C(myStack);
		C c2 = new C(myStack);
		C c3 = new C(myStack);
		C c4 = new C(myStack);
		ThreadP pThread = new ThreadP(p);
		pThread.start();
		ThreadC cThread1 = new ThreadC(c1);
		ThreadC cThread2 = new ThreadC(c2);
		ThreadC cThread3 = new ThreadC(c3);
		ThreadC cThread4 = new ThreadC(c4);
		
		cThread1.start();
		cThread2.start();
		cThread3.start();
		cThread4.start();
	}

}

package com.java.mul;

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

public class MyStack {
	private List list = new ArrayList();
	synchronized public void push() {
		try {
			while(list.size() == 1) {
				this.wait();
			}
			list.add("anyString=" + Math.random());
			this.notify();
			System.out.println("push=" + list.size());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	synchronized public String pop() {
		String returnValue = "";
		try {
			while(list.size()==0) {
				System.out.println("pop:"+ Thread.currentThread().getName() + " wait");
				this.wait();
			}
			returnValue = "" + list.get(0);
			list.remove(0);
			this.notify();
			System.out.println("pop="+list.size());
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnValue;
	}
}

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

java的JDK中提供了4个类来使线程间可以进行通信:

PipedInputStreeam和PipedOutputStreeam

PipedReader和PipedWriter

 

 

实战:等待/通知之交叉备份

package com.java.mul;

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) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	synchronized public void backupB(){
		try {
			while(prevIsA == false) {
				wait();
			}
			for(int i=0;i<5;i++) {
				System.out.println("22222");
			}
			prevIsA = false;
			notifyAll();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

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

package com.java.mul;

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

package com.java.mul;

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

public class Run {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		DBTools dbtools = new DBTools();
		for(int i = 0;i<20;i++) {
			BackupB output = new BackupB(dbtools);
			output.start();
			BackupA input = new BackupA(dbtools);
			input.start();
		}
			
	}
}

 

方法join的使用(等待线程对象销毁)

join在内部使用wait方法进行等待,synchronized关键字使用的是“对象监视器”原理作为同步。

方法join后的代码可能异步提前运行,造成多种结果的组合。

 

类ThreadLocal的使用(使每一个线程都有一个自己的共享变量的值,也就是变量在不同线程的隔离性)

package com.java.mul;

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

public class Run {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			MyThreadA a = new MyThreadA();
			MyThreadB b = new MyThreadB();
			a.start();
			b.start();
			for(int i = 0;i<100;i++) {
				Tools.t1.set("Main" + (1 + i));
				System.out.println("Main get Value=" + Tools.t1.get());
				Thread.sleep(200);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
	}
}

package com.java.mul;

public class Tools {
	public static ThreadLocal t1 = new ThreadLocal();
}

package com.java.mul;

public class MyThreadA extends Thread{

	@Override
	public void run() {
		
		try {
			for(int i = 0;i<100;i++) {
				Tools.t1.set("ThreadA" + (1 + i));
				System.out.println("ThreadA get Value=" + Tools.t1.get());
				Thread.sleep(200);
			}

			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

package com.java.mul;

public class MyThreadB extends Thread{

	
	@Override
	public void run() {
				try {

						for(int i = 0;i<100;i++) {
							Tools.t1.set("ThreadB" + (1 + i));
							System.out.println("ThreadB get Value=" + Tools.t1.get());
							Thread.sleep(200);
						}
					
					
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			

	}
}


InheritableThreadLocal(使用这个类,可以使子线程继承父线程的值)

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值