Java多线程间的通信问题扩展
2014-12-01 22:27
225 查看
到底什么是线程间的通信?
线程间需要通过一些协调性的通信,实现共同完成同一件任务,简单说就是,你想做这件事,我也想做这件事,我们两个相互交流,共同做这件事,而共同任务的同步性的实现,就必须通过同步锁,每一个对象实例都有自己的一把锁,当一个线程想要对这个任务进行处理的时候,就必须获得这把锁。线程之间锁的释放与获取,是通过Object类中的wait()/notify()方法实现的。wait()方法是将当前拥有锁的线程至于等待状态让其释放锁,而notify()方法是唤醒其他线程使其具备执行资格,过来拿这个锁,拿到这个锁后才具备了执行权。
需要注意的是,一定要确保wait()方法是出于同步区域中,才会拥有锁,而同样至于同步区域的Thread.sleep()方法,只会让线程在指定的时间段内睡眠,而不会释放锁
线程间的通信主要通过两种方式:
1.共享内存
初次学习的时候,已经写过,写个简单点的
ps:共享内存这中通信方式,存在不稳定性,有时候会出现问题
2.管道流
通过管道流实现线程间的通信,主要是将管道流连接到线程。
ps:因为管道流的read方法是阻塞式的,数据的同步和并发会出现问题
由线程间的通信问题进而可以提升到多生产者多消费者问题
多生产者多消费者问题解决方法一般分为两种:
1.采用一种机制实现生产者/消费者间的同步(常用,效率高)
2.采用管道流的方式
解决同步问题,一般都是synchronized函数或代码块+while+notifyAll的方式,接口Lock的出现,有了更加灵活的操作,可以支持多个监听器,以此来实现锁更广泛的操作
此处直接演示Lock的方式
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by kevy on 14-12-01.
*/
/**
* 描述:仓库存储着货物,每个货物都对应一个编号
* 仓库货满时,生产者不能存放货物。 仓库为空时,消费者不能拿走货物
* 面向对象的思想考虑问题:涉及的对象,生产者,消费者,货物,仓库
* 生产者,消费者对应着同一个仓库,仓库对应着不同的货物
*/
class Goods {
private String name;
private int num;
Goods(String name,int num){
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
}
class StoreHouse{
public final static int SIZE = 10;
private Goods[] goodses = new Goods[SIZE];//定义仓库储存大小
private Lock lock = new ReentrantLock();//创建锁
private Condition Pro_lock = lock.newCondition();//创建生产者监视器
private Condition Cus_lock = lock.newCondition();//创建消费者监视器
private int putnum = 0,count = 0,takenum = 0;
public void set(Goods good){
lock.lock();
try{
while(count==SIZE){
try{
Pro_lock.await();
}catch (Exception e){
e.printStackTrace();
}
}
Thread.sleep(100);//延时100
goodses[putnum] = good;
System.out.println(Thread.currentThread().getName()+"++++生产++++"+
good.getName()+good.getNum());
if(++putnum==SIZE) putnum = 0;
count++;
Cus_lock.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void out(){
lock.lock();
try{
while(count==0){
try{
Cus_lock.await();
}catch(Exception e){
e.printStackTrace();
}
}
Thread.sleep(100);//延时100
Goods item = goodses[takenum];
if(++takenum==SIZE) takenum = 0;
--count;
System.out.println(Thread.currentThread().getName()+"----消费----"+
item.getName()+item.getNum());
Pro_lock.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
class Producer implements Runnable{
private StoreHouse storeHouse = null;
private String Goodname = null;
Producer(StoreHouse storeHouse,String goodname){
this.storeHouse = storeHouse;
this.Goodname = goodname;
}
public void run() {
int NUM = 1;
while(true){
storeHouse.set(new Goods(Goodname,NUM++));
}
}
}
class Customer implements Runnable{
private StoreHouse storeHouse = null;
Customer(StoreHouse storeHouse){
this.storeHouse = storeHouse;
}
public void run() {
while(true){
storeHouse.out();
}
}
}
public class Main {
public static StoreHouse storeHouse;
public static void main(String[] args){
storeHouse = new StoreHouse();
Runnable p = new Producer(storeHouse,"卫生纸");
Runnable p1 = new Producer(storeHouse,"Java技术-核心卷I");
Runnable c = new Customer(storeHouse);
Runnable c1 = new Customer(storeHouse);
Thread proThread1 = new Thread(p);//生产者线程
Thread proThread2 = new Thread(p1);
Thread cusThread1 = new Thread(c);//消费者线程
Thread cusThread2 = new Thread(c1);
proThread1.start(); cusThread1.start();
proThread2.start(); cusThread2.start();
}
}
线程间需要通过一些协调性的通信,实现共同完成同一件任务,简单说就是,你想做这件事,我也想做这件事,我们两个相互交流,共同做这件事,而共同任务的同步性的实现,就必须通过同步锁,每一个对象实例都有自己的一把锁,当一个线程想要对这个任务进行处理的时候,就必须获得这把锁。线程之间锁的释放与获取,是通过Object类中的wait()/notify()方法实现的。wait()方法是将当前拥有锁的线程至于等待状态让其释放锁,而notify()方法是唤醒其他线程使其具备执行资格,过来拿这个锁,拿到这个锁后才具备了执行权。
需要注意的是,一定要确保wait()方法是出于同步区域中,才会拥有锁,而同样至于同步区域的Thread.sleep()方法,只会让线程在指定的时间段内睡眠,而不会释放锁
线程间的通信主要通过两种方式:
1.共享内存
初次学习的时候,已经写过,写个简单点的
public class Main{ public static void main(String[] args){ MemoryThread MyThread = new MemoryThread(); MyThread.getThread().start(); MyThread.getThread().start(); } } class MemoryThread { private int data; public MemoryThread() { // TODO Auto-generated constructor stub data = 0; } public class Inside implements Runnable{ public void run() { while(true){ synchronized (this) { System.out.println(Thread.currentThread().getName()+"--:--"+(++data)); } } } } public Thread getThread(){ return new Thread(new Inside()); } }
ps:共享内存这中通信方式,存在不稳定性,有时候会出现问题
2.管道流
通过管道流实现线程间的通信,主要是将管道流连接到线程。
class Producer implements Runnable{ private PipedOutputStream pout = null; public Producer(PipedOutputStream pout) { this.pout = pout; } public void run() { int x = 1; // TODO Auto-generated method stub synchronized (this) { while(true){ synchronized (this) { try { System.out.println("Producer set "+x); pout.write(x); } catch (Exception e) { e.printStackTrace(); } } } } } } class Customer implements Runnable{ private PipedInputStream pin = null; public Customer(PipedInputStream pin) { this.pin = pin; } public void run() { while(true){ synchronized(this){ try { System.out.println("Customer get "+pin.read()); } catch (Exception e) { // TODO: handle exception } } } } } public class Main{ public static void main(String[] args) { PipedInputStream pin = new PipedInputStream(); PipedOutputStream pot = new PipedOutputStream(); try{ pot.connect(pin); }catch(Exception e){ e.printStackTrace(); } new Thread(new Producer(pot)).start(); new Thread(new Customer(pin)).start(); } }
ps:因为管道流的read方法是阻塞式的,数据的同步和并发会出现问题
由线程间的通信问题进而可以提升到多生产者多消费者问题
多生产者多消费者问题解决方法一般分为两种:
1.采用一种机制实现生产者/消费者间的同步(常用,效率高)
2.采用管道流的方式
解决同步问题,一般都是synchronized函数或代码块+while+notifyAll的方式,接口Lock的出现,有了更加灵活的操作,可以支持多个监听器,以此来实现锁更广泛的操作
此处直接演示Lock的方式
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by kevy on 14-12-01.
*/
/**
* 描述:仓库存储着货物,每个货物都对应一个编号
* 仓库货满时,生产者不能存放货物。 仓库为空时,消费者不能拿走货物
* 面向对象的思想考虑问题:涉及的对象,生产者,消费者,货物,仓库
* 生产者,消费者对应着同一个仓库,仓库对应着不同的货物
*/
class Goods {
private String name;
private int num;
Goods(String name,int num){
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
}
class StoreHouse{
public final static int SIZE = 10;
private Goods[] goodses = new Goods[SIZE];//定义仓库储存大小
private Lock lock = new ReentrantLock();//创建锁
private Condition Pro_lock = lock.newCondition();//创建生产者监视器
private Condition Cus_lock = lock.newCondition();//创建消费者监视器
private int putnum = 0,count = 0,takenum = 0;
public void set(Goods good){
lock.lock();
try{
while(count==SIZE){
try{
Pro_lock.await();
}catch (Exception e){
e.printStackTrace();
}
}
Thread.sleep(100);//延时100
goodses[putnum] = good;
System.out.println(Thread.currentThread().getName()+"++++生产++++"+
good.getName()+good.getNum());
if(++putnum==SIZE) putnum = 0;
count++;
Cus_lock.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void out(){
lock.lock();
try{
while(count==0){
try{
Cus_lock.await();
}catch(Exception e){
e.printStackTrace();
}
}
Thread.sleep(100);//延时100
Goods item = goodses[takenum];
if(++takenum==SIZE) takenum = 0;
--count;
System.out.println(Thread.currentThread().getName()+"----消费----"+
item.getName()+item.getNum());
Pro_lock.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
class Producer implements Runnable{
private StoreHouse storeHouse = null;
private String Goodname = null;
Producer(StoreHouse storeHouse,String goodname){
this.storeHouse = storeHouse;
this.Goodname = goodname;
}
public void run() {
int NUM = 1;
while(true){
storeHouse.set(new Goods(Goodname,NUM++));
}
}
}
class Customer implements Runnable{
private StoreHouse storeHouse = null;
Customer(StoreHouse storeHouse){
this.storeHouse = storeHouse;
}
public void run() {
while(true){
storeHouse.out();
}
}
}
public class Main {
public static StoreHouse storeHouse;
public static void main(String[] args){
storeHouse = new StoreHouse();
Runnable p = new Producer(storeHouse,"卫生纸");
Runnable p1 = new Producer(storeHouse,"Java技术-核心卷I");
Runnable c = new Customer(storeHouse);
Runnable c1 = new Customer(storeHouse);
Thread proThread1 = new Thread(p);//生产者线程
Thread proThread2 = new Thread(p1);
Thread cusThread1 = new Thread(c);//消费者线程
Thread cusThread2 = new Thread(c1);
proThread1.start(); cusThread1.start();
proThread2.start(); cusThread2.start();
}
}
相关文章推荐
- java多线程-线程间通信-示例代码-解决安全问题-等待唤醒机制wait()notify()notifyAll()
- 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)
- SendMessage进程间简单通信问题
- Server Client 分工和通信问题。
- [疑难杂症]扩展AxWebBrowser的问题???
- 关于server to server通信时dialback握手的问题
- Sybase ASE段不能自动扩展空间的问题
- 在Windows 2003下安装FrontPage服务器扩展遇到的问题
- 现代通信原理 问题解答
- 关于dotnet的异步socket通信的问题
- PDA和蓝牙模块之间的通信问题!
- 解决Java Applet和Java Script通信问题
- *.jspf扩展名文件在jsp:include、@include和c:import中的区别、问题和解决
- java与c/c++进行socket通信的一些问题(2)
- 从面向结构到面向对象-----josephus扩展问题(一)
- 三菱PLC FX系列编程口通信的若干问题
- LabVIEW中的串口通信问题
- 最近碰到个问题,关于php扩展编程如何返回数组的问题
- MSComm控件在中文Windows下的通信问题与处理方法