一,先不考虑线程安全的问题,对该事件分析并编写如下代码
Cake类:
package test_3;
public class Cake {
private int sum=0;
private static final int MAX_SIZE=20;
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public void produce(String pname){
sum++;
System.out.println(pname+"生产了一个cake,现在还有"+sum);
}
public void sell(String cname){
sum--;
System.out.println(cname+"消费了一个cake,现在还有"+sum);
}
}
Producer类:
package test_3;
public class Producer implements Runnable{
private Cake cake;
public Producer(Cake cake) {
this.cake = cake;
}
@Override
public void run() {
for (int i=0;i<50;i++){
cake.produce(Thread.currentThread().getName());
}
}
}
Consumer类:
package test_3;
public class Consumer implements Runnable{
private Cake cake;
public Consumer(Cake cake) {
this.cake = cake;
}
@Override
public void run() {
for(int i=0;i<50;i++){
cake.sell(Thread.currentThread().getName());
}
}
}
Main类:
package test_3;
public class Main {
public static void main(String[] args) {
Cake cake = new Cake();
new Thread(new Consumer(cake),"消费者一").start();
new Thread(new Producer(cake),"生产者一").start();
new Thread(new Producer(cake),"生产者二").start();
new Thread(new Consumer(cake),"消费者二").start();
}
}
二,进行分析,需要加锁的对象为Cake,对Cake类的代码进行如下修改
package test_3;
public class Cake {
private int sum=0;
private static final int MAX_SIZE=20;
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public synchronized void produce(String pname){
if(sum>=MAX_SIZE){
try {
System.out.println("已达最大量!!!");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sum++;
System.out.println(pname+"生产了一个cake,现在还有"+sum);
this.notifyAll();
}
public synchronized void sell(String cname){
if(sum<=0){
try {
System.out.println("已售完!!!");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sum--;
System.out.println(cname+"消费了一个cake,现在还有"+sum);
this.notifyAll();
}
}
线程安全问题解决,如果不清楚或是思路不太清晰,可以将问题分解进行解决
三,使用lock锁实现
package test_3;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Cake_1 {
private int sum=0;
private static final int MAX_SIZE=20;
private Lock lock = new ReentrantLock();
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
public void produce(String pname){
if(sum>=MAX_SIZE){
lock.lock();
System.out.println("已达最大量!!!");
lock.unlock();
}
else{
lock.lock();
sum++;
System.out.println(pname+"生产了一个cake,现在有"+sum);
lock.unlock();
}
}
public synchronized void sell(String cname){
if(sum<=0){
lock.lock();
System.out.println("已售完!!!");
lock.unlock();
}
else{
lock.lock();
sum--;
System.out.println(cname+"消费了一个cake,现在还有"+sum);
lock.unlock();
}
}
}
四,使用阻塞队列BlockingQueue
package test_3;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Cake_2 {
private BlockingQueue queue = new LinkedBlockingQueue(20);
public void produce(String pname){
try {
queue.put("new cake");
System.out.println(pname+"生产了一个cake,还有"+queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sell(String cname){
try {
queue.take();
System.out.println(cname+"消费了一个cake,还有"+queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用阻塞对列先比前两个方法会简单一些,不需要去考虑 空 或 满 的状态,这是由于BlockingQueue 的实现LinkedBlockingQueue所决定的