过多的线程同步可能会造成死锁 死锁通俗来讲就是两个或者两个以上线程,占用了对方下一步所需要的资源,多个线程僵持都无法结束任务的状态 生产者和消费者模式是一个多线程同步的经典案例 它利用信号灯来判断线程是否可以执行,可以避免线程的死锁问题 在java
Java实现线程的同步,可以通过synchronized,wait(), notitfy(), notifyAll();假设一个线程(生产者)生产产品,一个线程(消费者)消费产品,其访问的资源时间都是随机的,这样就是生产者必须得产品(资源)消费完成之后才可以生产,而消费者必须在产品有的时候才可以消费,这就是必须对资源进行同步操作,对资源的使用部分的代码需要加入锁。
下列是我的实现方法:
/**
* ProducterCustomer.java V1.0 Apr 28, 2012 3:06:44 PM
*
* Copyright Lizhenbin Co. ,Ltd. All rights reserved.
*
* Modification history(By Time Reason):
*
* Description:
*/
package com.lzb.common;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
*
* 功能描述:生产者消费者
* 注:锁synhronized是放在“资源的类的内部方法中”,而不是在线程的代码中
*
* @author lizhenbin
*
*
修改历史:(修改人,修改时间,修改原因/内容)
*/
public class ProducterCustomer {
private PCResource pc = new PCResource();
// 生产者与消费者调用的时间随机
private Random rand = new Random(50);
public void init() {
// 生产者
new Thread(new Runnable(){
public void run() {
while(true) {
pc.producter();
try {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}}).start();
// 消费者
new Thread(new Runnable(){
public void run() {
while(true) {
pc.customer();
try {
TimeUnit.MILLISECONDS.sleep(rand.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}}).start();
}
public static void main(String[] args) {
ProducterCustomer startPc = new ProducterCustomer();
startPc.init();
}
}
/**
*
* 功能描述:同步资源
*
* @author lizhenbin
*
*
修改历史:(修改人,修改时间,修改原因/内容)
*/
class PCResource {
private static final Integer MAX = 1;
private static final Integer MIN = 0;
private int product = 0;
// 同步互斥通信标志
private boolean isRunning = true;
/**
*
* 功能描述:生产产品,当生产一个商品后挂起,等待消费者消费完成
*
* @author lizhenbin
*
创建日期 :Apr 28, 2012 3:49:07 PM
*
*
*
修改历史 :(修改人,修改时间,修改原因/内容)
*/
public synchronized void producter() {
while(isRunning) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
product++;
System.out.println("-------->Product " + product + " good");
if(product >= MAX)
break;
}
isRunning = false;
notify();
}
/**
*
* 功能描述:消费者,消费产品,当产品为0时,等待生产者生产产品
*
* @author lizhenbin
*
创建日期 :Apr 28, 2012 3:49:50 PM
*
*
*
修改历史 :(修改人,修改时间,修改原因/内容)
*/
public synchronized void customer() {
while(!isRunning) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
product--;
System.out.println("Limit " + product + " goods
if(product <= MIN) {
break;
}
}
isRunning = true;
notify();
}
}
线程间通信:生产者消费者(等待唤醒机制) public classStudent { Stringname; int age; boolean flag; // 默认情况是没有数据,如果是true,说明有数据 } public classSetThread implementsRunnable { private Student s; private int x
自己学习多线程的时候,模拟实现了一个生产者消费者的一个查询。
1. 生产者代码:
package com.lzb.thread;
/**
* 生产者
* @author lizhenbin
*
*/
public class Producer implements Runnable {
private static String P_ID = "生产者";
private static String P_CONTEXT = "生产了一个产品";
private CallResource cr;
/**
* 构造和消费者使用的是用以资源
* @param cr
*/
public Producer(CallResource cr) {
this.cr = cr;
}
public void run() {
// TODO Auto-generated method stub
while(true) {
while(true) {
cr.producerMethod(P_ID, P_CONTEXT);
//线程休眠
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
2. 消费者
package com.lzb.thread;
/**
* 生产者
* @author lizhenbin
*
*/
public class Consumer implements Runnable {
private static String C_ID = "消费者";
private static String C_CONTEXT = "消费了一个产品";
private CallResource cr;
/**
* 构造和生产者使用的是用以资源
* @param cr
*/
public Consumer(CallResource cr) {
this.cr = cr;
}
public void run() {
// TODO Auto-generated method stub
while(true) {
cr.consumerMetod(C_ID, C_CONTEXT);
//线程休眠
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3. 生产者消费者共同使用的资源,这里设置为只有一个商品的形式
package com.lzb.thread;
/**
* 生产者与消费者共同使用的资源
* @author lizhenbin
*
*/
public class CallResource {
/**
* 创建两个属性验证同步
*/
private String resourceId;
private String context;
private int flag = 0; //生产的产品数
/**
* 生产者生产产品
* @param id
* @param context
* @param num
*/
public synchronized void producerMethod(String id, String context){
if(this.flag == 1) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.resourceId = id;
this.context = context;
this.flag++;
this.notify();
System.out.println(this.resourceId+" , "+this.context+" , "+" 产品数: "+this.flag);
}
/**
*
* @param id
* @param context
* @param num
*/
public synchronized void consumerMetod(String id, String context) {
if(this.flag == 0) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.resourceId = id;
this.context = context;
this.flag--;
this.notify();
System.out.println(this.resourceId+" , "+this.context+" , "+" 产品数: "+this.flag);
}
}
4. 线程调用
package com.lzb.thread;
/**
* 启动线程
* @author lizhenbin
*
*/
public class MainProcess {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
CallResource cr = new CallResource();
Producer p = new Producer(cr);
Consumer c = new Consumer(cr);
Thread pthread = new Thread(p);
Thread cthread = new Thread(c);
pthread.start();
cthread.start();
}
}