您的位置:首页 > 编程语言 > Java开发

Java多线程间的通信问题扩展

2014-12-01 22:27 225 查看
到底什么是线程间的通信?

线程间需要通过一些协调性的通信,实现共同完成同一件任务,简单说就是,你想做这件事,我也想做这件事,我们两个相互交流,共同做这件事,而共同任务的同步性的实现,就必须通过同步锁,每一个对象实例都有自己的一把锁,当一个线程想要对这个任务进行处理的时候,就必须获得这把锁。线程之间锁的释放与获取,是通过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();

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: