目录
练习1
/**
* 经典例题:生产者和消费着问题
* <p>
* 生产者( Productor)将产品交给店员( Clerk),
* 而消费者( (Customer)从店员处取走产品,
* 店员一次只能持有固定数量的产品(比如:20),
* 如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;
* 如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
*/
提示:以下是本篇文章正文内容,下面案例可供参考
代码如下(示例):
package com.java.thread.practice;
/**
* 经典例题:生产者和消费着问题
* <p>
* 生产者( Productor)将产品交给店员( Clerk),
* 而消费者( (Customer)从店员处取走产品,
* 店员一次只能持有固定数量的产品(比如:20),
* 如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;
* 如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
*/
class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer p1 = new Producer(clerk);
Producer p2 = new Producer(clerk);
p1.setName("生产者1");
p2.setName("生产者2");
Consumer c1 = new Consumer(clerk);
Consumer c2 = new Consumer(clerk);
c1.setName("消费者1");
c2.setName("消费者2");
p1.start();
c1.start();
}
}
/**
* 店员
*/
class Clerk {
private int productNum; // 商品数量
public Clerk() {
this.productNum = 0;
}
public int getProductNum() {
return productNum;
}
public void setProductNum(int productNum) {
this.productNum = productNum;
}
}
/**
* 生产者
*/
class Producer extends Thread {
private Clerk clerk;
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始生产......");
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
produce();
}
}
public Producer(Clerk clerk) {
if (clerk != null) {
this.clerk = clerk;
}
}
private void produce() {
synchronized (ProductTest.class) {
ProductTest.class.notify();
if (clerk.getProductNum() < 20) {
clerk.setProductNum(clerk.getProductNum() + 1);
System.out.println(Thread.currentThread().getName() + ":\t生产完成第 " + clerk.getProductNum() + " 个产品");
}else {
try {
ProductTest.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 消费者
*/
class Consumer extends Thread {
private Clerk clerk;
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始消费......");
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
buy();
}
}
public Consumer(Clerk clerk) {
if (clerk != null) {
this.clerk = clerk;
}
}
private void buy(){
synchronized (ProductTest.class) {
ProductTest.class.notify();
if (clerk.getProductNum() > 0) {
System.out.println(Thread.currentThread().getName() + ":\t购买完成第 " + clerk.getProductNum() + " 个产品");
clerk.setProductNum(clerk.getProductNum() - 1);
}else {
try {
ProductTest.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
练习2
/**
* 练习2
* 银行有一个账户
* 有两个储户分别向同一个账户存 3000 元,每次存 1000 ,存 3 次。每次存完打印账户余额。
* 分析:
* 1.是否有多个线程问题?
* 2.是否有共享数据?
* 3.是否有线程安全问题?
*/
package com.java.thread.practice;
public class AccountTest {
public static void main(String[] args) {
Account acct = new Account();
Customer c1 = new Customer(acct);
Customer c2 = new Customer(acct);
c1.setName("储户1");
c2.setName("储户2");
c1.start();
c2.start();
}
}
class Account {
private double accountSum;
public Account() {
this.accountSum = 0;
}
public Account(double accountSum) {
this.accountSum = accountSum;
}
//存钱
public void deppsit(double depositNum) {
synchronized (this) {
if (depositNum > 0) {
accountSum = accountSum + depositNum;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": 存钱成功,当前余额为:\t" + accountSum);
}
}
}
}
class Customer extends Thread {
private Account acct;
public Customer(Account acct) {
this.acct = acct;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
acct.deppsit(1000);
}
}
}
总结
分析:
* 1.是否有多个线程问题? 是,有两个储户线程。
* 2.是否有共享数据? 是,两个储户向同一个账户存钱
* 3.是否有线程安全问题: 有