线程案例
1、创建店员,可以进货,卖货
class Clerk{
private int product=10;//店里只能放10个货
//进货
public synchronized void get(){
if(product>=10){ //如果店里的货物大于等于10,提醒货满了
System.out.println("货满了");
}else{
System.out.println("进货>"+ ++product); //货不满,进货
}
}
//卖货
public synchronized void sale(){
if(product<=0){ //如果货小鱼等于0,表示缺货,无法销售
System.out.println("缺货");
}else{
System.out.println("进货>"+ --product); //有货,可销售
}
}
}
2、创建生产者,消费者
//供货商供货
class Supplier implements Runnable{
private Clerk clerk;
public Supplier(Clerk clerk) { //供货商找到店员,你从我这进货
this.clerk=clerk;
}
@Override
public void run() {
for(int i=0;i<20;i++){
clerk.get();
}
}
}
//消费者
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) { //消费者找到店员,我从你这买
this.clerk=clerk;
}
@Override
public void run() {
for(int i=0;i<20;i++){
clerk.sale();
}
}
}
3、运行
public static void main(String[] args){
Clerk clerk=new Clerk();
new Thread(new Supplier(clerk),"生产者").start();
new Thread(new Consumer(clerk),"消费者").start();
}
分析:
1、供货商发现商品满了,会一直提醒店员货满了
2、消费者发现没货了,会一直提醒店员缺货
解决:如果满了,等待,缺货,等待,不满通知
修改代码如下
class Clerk{
private int product=10;//店里只能放10个货
//进货
public synchronized void get(){
if(product>=10){ //如果店里的货物大于等于10,提醒货满了
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("货满了");
}else{
this.notifyAll();
System.out.println("进货>"+ ++product); //货不满,进货
}
}
//卖货
public synchronized void sale(){
if(product<=0){ //如果货小鱼等于0,表示缺货,无法销售
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("缺货");
}else{
this.notifyAll();
System.out.println("卖货>"+ --product); //有货,可销售
}
}
}
运行结果
4、此时在消费这延时消费
//消费者
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) { //消费者找到店员,我从你这买
this.clerk=clerk;
}
@Override
public void run() {
for(int i=0;i<20;i++){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.sale();
}
}
}
切存货最大为1
//进货
public synchronized void get(){
if(product>=1){ //如果店里的货物大于等于10,提醒货满了
...
此时会出现问题,运行结束,但是程序没有停止
究其原因:是因为
问题处理结果:
将else放开
class Clerk{
private int product=10;//店里只能放10个货
//进货
public synchronized void get(){ //剩余2次 发现product=0,执行++product,product=1,唤醒操作,下次再次执行,会执行此处wait(),程序已走完一直在wait();
if(product>=1){ //如果店里的货物大于等于10,提醒货满了
try {
this.wait(); //如果货满了,等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("货满了");
}
System.out.println("进货>"+ ++product); //货不满,进货
this.notifyAll(); //不满的时候通知,进货
}
//卖货
public synchronized void sale(){ //执行完,product=0,执行wait();这时,继续执行get(),发现product=0;
if(product<=0){ //如果货小鱼等于0,表示缺货,无法销售
try {
this.wait(); //缺货,等待,不销售
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("缺货");
}
System.out.println("卖货>"+ --product); //有货,可销售
this.notifyAll(); //有货,通知卖
}
}
接下来,多个供货商,多个消费者
public static void main(String[] args){
Clerk clerk=new Clerk();
new Thread(new Supplier(clerk),"生产者").start();
new Thread(new Consumer(clerk),"消费者").start();
new Thread(new Supplier(clerk),"生产者1").start();
new Thread(new Consumer(clerk),"消费者1").start();
}
执行出现问题:
卖货很多,但是根本没有,虚假
解决:wait()应总是使用在循环中
if编程while
class Clerk{
private int product=10;//店里只能放10个货
//进货
public synchronized void get(){ //剩余2次 发现product=0,执行++product,product=1,唤醒操作,下次再次执行,会执行此处wait(),程序已走完一直在wait();
while (product>=1){ //如果店里的货物大于等于10,提醒货满了
try {
this.wait(); //如果货满了,等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("货满了");
}
System.out.println("进货>"+ ++product); //货不满,进货
this.notifyAll(); //不满的时候通知,进货
}
//卖货
public synchronized void sale(){ //执行完,product=0,执行wait();这时,继续执行get(),发现product=0;
while(product<=0){ //如果货小鱼等于0,表示缺货,无法销售
try {
this.wait(); //缺货,等待,不销售
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("缺货");
}
System.out.println("卖货>"+ --product); //有货,可销售
this.notifyAll(); //有货,通知卖
}
}
结果:
另一种解决方式
使用Lock 和 Condition
package test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test2 {
public static void main(String[] args){
Clerk clerk=new Clerk();
new Thread(new Supplier(clerk),"生产者").start();
new Thread(new Consumer(clerk),"消费者").start();
new Thread(new Supplier(clerk),"生产者1").start();
new Thread(new Consumer(clerk),"消费者1").start();
}
}
class Clerk{
private int product=0;//店里只能放10个货
private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
//进货
public void get(){
lock.lock();
try {
while (product>=1){ //如果店里的货物大于等于10,提醒货满了
try {
condition.await(); // 对应 this.wait(); //如果货满了,等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("货满了");
}
System.out.println("进货>"+ ++product); //货不满,进货
condition.signalAll(); // 对应 this.notifyAll(); //不满的时候通知,进货
}finally {
lock.unlock();
}
}
//卖货
public void sale(){
lock.lock();
try {
while(product<=0){ //如果货小鱼等于0,表示缺货,无法销售
try {
condition.await(); // 对应 this.wait(); //缺货,等待,不销售
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("缺货");
}
System.out.println("卖货>"+ --product); //有货,可销售
condition.signalAll(); // 对应 this.notifyAll(); //有货,通知卖
}finally {
lock.unlock();
}
}
}
//供货商供货
class Supplier implements Runnable{
private Clerk clerk;
public Supplier(Clerk clerk) { //供货商找到店员,你从我这进货
this.clerk=clerk;
}
@Override
public void run() {
for(int i=0;i<20;i++){
clerk.get();
}
}
}
//消费者
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) { //消费者找到店员,我从你这买
this.clerk=clerk;
}
@Override
public void run() {
for(int i=0;i<20;i++){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.sale();
}
}
}
实例:三个线程按照顺序循环打印ABCABCABC…
package test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test3 {
public static void main(String[] args){
Print print = new Print();
new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<=20;i++){
print.printA();
}
}
},"A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<=20;i++){
print.printB();
}
}
},"B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<=20;i++){
print.printC();
System.out.println("--------------------------------");
}
}
},"C").start();
}
}
class Print{
private int currentThreadId=1;
private Lock lock = new ReentrantLock();
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
private Condition condition3=lock.newCondition();
public void printA(){
lock.lock();
try {
if(currentThreadId !=1){
condition1.await();
}
System.out.println("A");
currentThreadId=2;
condition2.signal();
}catch (Exception e){
}
finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
if(currentThreadId !=2){
condition2.await();
}
System.out.println("B");
currentThreadId=3;
condition3.signal();
}catch (Exception e){
}
finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
if(currentThreadId !=3){
condition3.await();
}
System.out.println("C");
currentThreadId=1;
condition1.signal();
}catch (Exception e){
}
finally {
lock.unlock();
}
}
}
结果: