1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 多线程:线程同步与死锁(卖票案例) 线程通信 生产者与消费者

多线程:线程同步与死锁(卖票案例) 线程通信 生产者与消费者

时间:2019-01-11 02:15:41

相关推荐

多线程:线程同步与死锁(卖票案例) 线程通信 生产者与消费者

卖票案例

5个窗口同时卖票:

使用Runnable接口,只创建了一个ticket1对象,5个线程共享此对象,实现了资源共享。

public class ticket1 implements Runnable {private int ticket = 5;@Overridepublic void run(){for (int i = 0; i < 10; i++) {if(ticket > 0){System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"张票");}}}public static void main(String[] args) {ticket1 ticket1 = new ticket1();Thread t1 = new Thread(ticket1);Thread t2 = new Thread(ticket1);Thread t3 = new Thread(ticket1);Thread t4 = new Thread(ticket1);Thread t5 = new Thread(ticket1);t1.start();t2.start();t3.start();t4.start();t5.start();}}

输出:

Thread-1正在出售第5张票Thread-2正在出售第3张票Thread-0正在出售第4张票Thread-3正在出售第1张票Thread-1正在出售第2张票

问题:

售票的顺序不对,应该以售出第5 - 4 - 3 - 2 - 1 张票的顺序

解决方法

1. 使用同步代码块

public class ticketSyn1 implements Runnable {

private int ticket = 5;@Overridepublic void run() {for (int i = 0; i < 10; i++) {synchronized (this) {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");}}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {ticketSyn1 ticket1 = new ticketSyn1();Thread t1 = new Thread(ticket1, "A");Thread t2 = new Thread(ticket1, "B");Thread t3 = new Thread(ticket1, "C");Thread t4 = new Thread(ticket1, "D");Thread t5 = new Thread(ticket1, "E");t1.start();t2.start();t3.start();t4.start();t5.start();}

使用同步方法

public class ticketSyn2 implements Runnable {private int ticket = 5;@Overridepublic void run() {for (int i = 0; i < 10 ; i++) {this.sell();try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void sell(){if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票");}}public static void main(String[] args) {ticketSyn2 ticket1 = new ticketSyn2();Thread t1 = new Thread(ticket1, "A");Thread t2 = new Thread(ticket1, "B");Thread t3 = new Thread(ticket1, "C");Thread t4 = new Thread(ticket1, "D");Thread t5 = new Thread(ticket1, "E");t1.start();t2.start();t3.start();t4.start();t5.start();}}

总结

同步代码块中的 synchronized(obj){}中的obj可为任何对象,推荐使用共享资源作为同步监视器。

练习

需求说明

张三和妻子各拥有一张银行卡和存折,可以对同一个银行账户迚行存取款的操作,请使用多线程及同步方法模拟张三和妻子同时取款的过程。要求使用同步方法和同步代码块两种方式实现

分析

定义Account类表示银行帐户

定义两个线程分别实现张三和妻子取款的操作

public class Account implements Runnable{private float money;public Account(){};public Account(float money) {this.money = money;}public float getMoney() {return money;}public void setMoney(float money) {this.money = money;}@Overridepublic void run() {for (int i = 0; i < 5; i++) {this.withdraw(400);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void withdraw(float withdrawMoney){System.out.println(Thread.currentThread().getName()+"正在取款");if(money >= withdrawMoney){money = money - withdrawMoney;System.out.println(Thread.currentThread().getName()+"取款成功!余额为"+money);}else {System.out.println("余额不足!取款失败。余额为"+money);}}public static void main(String[] args) {Account account = new Account(2000);Thread t1 = new Thread(account,"张三");Thread t2 = new Thread(account,"张三妻子");t1.start();t2.start();}}

输出:

张三正在取款张三取款成功!余额为1600.0张三妻子正在取款张三妻子取款成功!余额为1200.0张三正在取款张三取款成功!余额为800.0张三妻子正在取款张三妻子取款成功!余额为400.0张三正在取款张三取款成功!余额为0.0张三妻子正在取款余额不足!取款失败。余额为0.0张三正在取款余额不足!取款失败。余额为0.0张三妻子正在取款余额不足!取款失败。余额为0.0张三正在取款余额不足!取款失败。余额为0.0张三妻子正在取款余额不足!取款失败。余额为0.0

死锁

同步可以保证资源共享操作的正确性,但是过多同步也会产生死锁。

死锁一般情况下表示相互等待,是程序运行时出现的一种文体

线程通信

Java提供了3 种方法解决线程间的通信问题:

void notify()

Wakes up a single thread that is waiting on this object’s monitor.

唤醒一个处于等待状态的线程

void notifyAll()

Wakes up all threads that are waiting on this object’s monitor.

唤醒所有处于等待状态的线程

void wait()

Causes the current thread to wait until it is awakened, typically by being notified or interrupted.

使此线程一直等待,直到它被其他线程通知

void wait​(long timeoutMillis)

Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

指定等待的毫秒时间

void wait​(long timeoutMillis, int nanos)

Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real

指定等待的毫秒、微秒时间

生产者与消费者案例

商品类:

public class Goods {private String brand;private String name;//默认最初无商品, flag = falseprivate boolean flag = false;public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getName() {return name;}public void setName(String name) {this.name = name;}public synchronized void get(){//flag == false 说明无商品,消费者线程等待,进入阻塞状态。if(!flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("消费者购买了"+this.getBrand()+this.getName());flag = false;//唤醒生产者线程进行生产notify();}public synchronized void set(String brand,String name){// flag == true 说明有商品,生产者线程等待,进入阻塞状态。if(flag){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}this.setName(name);this.setBrand(brand);System.out.println("生产者生产了"+this.getBrand()+this.getName());flag = true;//唤醒消费者去购买notify();}}

生产者类:

public class Producer implements Runnable{private Goods goods;public Producer(Goods goods){this.goods = goods;}@Overridepublic void run() {for (int i = 0; i < 10 ; i++) {if(i%2==0){goods.set("娃哈哈","矿泉水");goods.set("旺仔","牛奶");}}}}

消费者类:

public class Consumer implements Runnable{private Goods goods;public Consumer(Goods goods) {this.goods = goods;}@Overridepublic void run() {for (int i = 0; i < 10 ; i++) {goods.get();}}}

测试类:

public class Test {public static void main(String[] args) {Goods goods = new Goods();Producer producer = new Producer(goods);Consumer consumer = new Consumer(goods);Thread t1 = new Thread(producer);Thread t2 = new Thread(consumer);t1.start();t2.start();}}

输出:

生产者生产了娃哈哈矿泉水消费者购买了娃哈哈矿泉水生产者生产了旺仔牛奶消费者购买了旺仔牛奶生产者生产了娃哈哈矿泉水消费者购买了娃哈哈矿泉水生产者生产了旺仔牛奶消费者购买了旺仔牛奶生产者生产了娃哈哈矿泉水消费者购买了娃哈哈矿泉水生产者生产了旺仔牛奶消费者购买了旺仔牛奶生产者生产了娃哈哈矿泉水消费者购买了娃哈哈矿泉水生产者生产了旺仔牛奶消费者购买了旺仔牛奶生产者生产了娃哈哈矿泉水消费者购买了娃哈哈矿泉水生产者生产了旺仔牛奶消费者购买了旺仔牛奶

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。