Java多线程

下面代码在一些特定的情况有问题,请指出并改正

import java.util.List;
import java.util.ArrayList;
public class MyStack
{
    private List<String>stack=new ArrayList<String>();
    public synchronized void push(String value)
    {
    synchronized(this)
    {    
    stack.add(value);
    notify();
    }
}
public synchronized String pop() throws InterruptedException
{    
    synchronized(this)
    {
    if(stack.size()<=0)
    {
    wait();
    }
    return stack.remove(stack.size()-1);
}
}
}

看到这道题,我也楞了好久。发现自己JAVA多线程的知识掌握得不是很牢靠。

看书后原来啊这个代码在大部分情况下都能正常运行,但在下面的场景中会有问题。

在多线程访问这个栈的时候,如果有三个线程按照如下的顺序访问,问题就会暴露

一、线程1先执行pop操作,此时,list大小为0,因此会调用wait释放等待锁

二、线程2执行push操作,往队列里放了一个元素,这个线程会调用notify来唤醒等待的线程

三、就在此时线程3恰好也执行pop操作,那么线程1和线程3的执行顺序是无法保证的。如果恰好线程3先执行pop,执行完成后线程2被唤醒,此时线程2会执行return stack.remove(stack.size()-1)操作,由于此时队列为空,stack.size()的返回值为0,所以,程序会抛出java.lang.ArrayIndexOutOfBoundsException异常

解决办法即是在pop操作调用remove方法前加一次判断,判断列表里是否还有元素

public synchronized String pop() throws InterruptedException
{    
    synchronized(this)
    {
    if(stack.size()<=0)
    {
    wait();
    }
    if(stack.size()<=0)
    return null;
    else
    return stack.remove(stack.size()-1);
}
}

这样就解决了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值