首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Java中使用线程的ArrayList<object>操作

Java中使用线程的ArrayList<object>操作
EN

Stack Overflow用户
提问于 2015-08-04 09:03:32
回答 2查看 863关注 0票数 0

我试图在java中使用线程时结合使用list.addlist.remove来解决一个问题。假设我们和Stack一起玩

这是我的Stack定义类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.ArrayList;

public class Stack {

    private int size;
    private int maxSize;

    private final ArrayList<Object> list;

    public Stack(int size) {
        this.size = 0;
        this.maxSize = size;
        this.list = new ArrayList<Object>(size);
    }

    public boolean push(Object o) {
        if (size >= maxSize) {
            return false;
        }

        this.list.add(0, o);
        this.size++;
        return true;
    }

    public Object pop() {
        Object o;
        if (this.size == 0) {
            return null;
        }

        o = this.list.remove(0);
        this.size--;
        return o;
    }

    public int size() {
        return this.size;
    }
}

下面是我们如何在Java线程中使用堆栈

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
final Stack stack = new Stack(4);
for(int i = 0; i < 10000; i++) {
    final String data = "hello " + i;
    final int x = i;
    new Thread(new Runnable() {
        public void run() {
            if(x % 2 == 0) {
                System.out.println(stack.push(data));
            } else {
                System.out.println(stack.pop());
            }
        }
    }).start();
}

基本上,我们只需创建10000个线程来操作Stack对象。stack.push导致True (如果堆栈尚未满)或false (如果堆栈已经满),如果堆栈为空,则stack.pop结果为null

问题是:上面的Stack实现有什么问题,以及如何修复它?

到目前为止,我的分析是线程如何在java中运行。线程以并行方式运行,而不是按顺序运行。我试着执行这个程序,有时会出现异常IndexOutOfBounds。如果我的分析是正确的(或接近),有什么办法可以避免例外吗?也许在Stack类中包括一些检查方法?

如果我的分析是错误的,那么上面的实现有什么问题呢?以及如何修复它?

EN

回答 2

Stack Overflow用户

发布于 2015-08-04 09:07:16

上面的堆栈实现有什么问题?

当只有一个线程可以访问堆栈对象时,您的实现是好的。但是,如果至少有2个线程可以在同一个堆栈上执行pop和push操作-- https://stackoverflow.com/questions/34510/what-is-a-race-condition就会发生。JSR-133描述了java多线程的主要描述。

想象一下使用pop方法编写的代码的情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (this.size == 0) {
    return null;
}
o = this.list.remove(0);
  1. 如果条件为1,则执行第一个线程。
  2. 第二个线程执行相同的if条件-大小仍然是1。
  3. 首先,线程试图从列表中删除索引为0的元素-成功,大小变为0.
  4. 第二,当大小为0时,线程尝试从列表中删除索引为0的元素--异常抛出。

你需要确保有些事情发生在其他事件之前。其中一种方法是同步poppush方法。这可以通过在方法返回类型之前添加synchronized关键字来实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public synchronized boolean push(Object o) {...}

public synchronized Object pop() { ...}

这里,这两种方法都是同一个对象的synchronized -- this。因此,当一个线程通过执行thispush获得pop锁时,没有其他线程能够进入由同一个this对象锁定(同步)的代码块或方法。使用这些方法是完全线程安全的。

如果您使用一些同步集合而不是常规的ArrayList,您仍然会遇到麻烦,因为您的逻辑依赖于size变量,而前面的错误场景仍然有效。如果需要并发Stack实现,可以使用java.util.concurrent包中的LinkedBlockingDeque类。它还会更高效,因为向ArrayList的开头添加一个元素的成本非常高。但是,如果您想单独启用它,只需向poppush方法添加同步修饰符,并将列表更改为LinkedList

票数 4
EN

Stack Overflow用户

发布于 2015-08-04 11:15:37

@ka4eli告诉您为什么Stack类不是线程安全的,但这也是错误的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(x % 2 == 0) {
    System.out.println(stack.push(data));
} else {
    System.out.println(stack.pop());
}

即使您的堆栈是完全线程安全的,在其他情况下也一定会得到NullPointerExceptions。

不同步线程可以按任何顺序运行。仅仅因为您的程序在启动线程1之前启动线程0,并不意味着线程1在线程0(或任何其他线程)之前不会尝试从堆栈中弹出字符串。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31815217

复制
相关文章
flashfxp编辑文件显示活动编辑的取消办法
我一直在使用的是国产的8UFTP,但是最近win10系统貌似有点不和谐,编辑文件上传的时候会有一秒“未响应”的卡顿情况,所以有些别扭,又不想做回win7,所以就想起了比较强大的flashfxp。
李洋博客
2021/06/16
1.5K0
取消开机时显示DHCP
集成网卡解决方法: 开机按Del键进入Bios->Integrated Peripherals ->Onboard LAN Boot Rom 改为Disabled。
杨强生
2019/03/05
2.1K0
取消开机时显示DHCP
Linux下gdb使用gdb命令时显示找不到文件
用户10551528
2023/10/18
8070
Maven 错误找不到符号
当碰到maven错误:找不到符号问题时,通常第一反应应该是执行eclipse的Project -> Clean … -> Clean all projects,然后再执行maven clean,将项目清理一下,然后再试试,如果还是不能解决接着往下看。
我是李超人
2020/08/20
7.4K0
vs2010点调试,显示系统找不到指定的文件
首先,查看“项目”-“属性”-“链接器”-“常规”-“输出文件”,路劲是否是“bin/xxx.exe”, 如果是请继续看我的解答,否则请忽略下面的内容。 原因是用VS2010加载调试以前的VC6.0下
互联网金融打杂
2018/04/03
2.3K0
vs2010点调试,显示系统找不到指定的文件
git取消文件跟踪
在使用git的时候,有些文件是不需要上传的,所以就可以修改   .gitignore 
lin_zone
2018/08/15
1.3K0
git取消文件跟踪
《SpringCloud错误篇:application.yml文件显示灰色》
2.File Types—>Text—>application.yml删除
2020/11/13
1.4K0
《SpringCloud错误篇:application.yml文件显示灰色》
git取消文件跟踪
在使用git的时候,有些文件是不需要上传的,所以就可以修改 .gitignore
全栈程序员站长
2022/07/07
1.5K0
git取消文件跟踪
bootstrap-fileinput上传完文件后再打开上传文件界面显示取消按钮
Bootstrap File Input是一款基于bootstrap框架的html5上传文件插件,具体展示效果如下:
johnhuster的分享
2022/03/28
1.8K0
bootstrap-fileinput上传完文件后再打开上传文件界面显示取消按钮
git 取消文件跟踪
git rm --cached readme1.txt    删除readme1.txt的跟踪,并保留在本地。
西湖醋鱼
2020/12/30
1.5K0
pycharmimport时找不到指定文件_pycharm系统找不到指定文件
Error running ‘hello’: Cannot run program “B:\pystudy\venv\Scripts\python.exe” (in directory “\python-study”): CreateProcess error=2, 系统找不到指定的文件。
全栈程序员站长
2022/09/27
5.7K0
pycharmimport时找不到指定文件_pycharm系统找不到指定文件
git 取消托管文件
如果想要取消托管某文件夹,通过如下命令能解决: git rm -r --cached .idea #--cached不会把本地的.idea删除 git commit -m '描述信息' git push -u origin master
week
2019/08/14
2.6K0
git取消跟踪文件
取消跟踪文件: $git rm --cached FILENAME 取消跟踪目录: $git rm --cached FILENAME -r   最佳解决方案: 先清空,再加回来。 git rm -r --cached . #删除追踪状态 git add . git commit -m "fixed untracked files"
Ryan-Miao
2018/03/13
7540
JavaScript实现显示时间,暂停时间,和取消显示时间
//显示时间函数 var id;//设置该id主要是为了之后的暂停和取消显示时间用到clearInterval(这里传id); function showTime(){ var divOne=document.getElementById("one"); var d=new Date(); var timStr=d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+" "+ d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()+":"+d.getMilliseconds(); divOne.innerHTML=timStr; id=setInterval(function(){ d=new Date(); timStr=d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+" "+ d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()+":"+d.getMilliseconds(); divOne.innerHTML=timStr; }, 1) }
小小鱼儿小小林
2020/06/23
2.3K0
点击显示错误
双折线点击一个,另一显示a b 错误.PNG 正确.PNG 隐藏一条线 tooltip: { // 气泡 trigger: "axis"
用户4344670
2019/08/28
1.2K0
点击显示错误
小程序开发找不到appjson_appjson文件内容错误未找到
– 问题原因: 导入微信开发者工具后project.config.json文件被微信开发者工具修改,缺少代码:“miniprogramRoot”: “./dist”从而导致微信开发者工具无法找到app.json文件进而报错:app.json: app.json 未找到,所以需要找到app.json 文件所在的文件夹,然后在project.config.json文件里写上aap.json的路径重新运行即可。
全栈程序员站长
2022/11/04
3.1K0
小程序开发找不到appjson_appjson文件内容错误未找到
Typecho评论回复取消回复按钮合并显示
第一步屏蔽默认评论js 将header.php中的header(); ?>改为header('commentReply='); ?> 第二步放置重构的js代码 将下面的一堆js代码放到comment
泽泽社长
2023/04/17
1.2K0
Typecho评论回复取消回复按钮合并显示
「R」显示英文错误
中文使用 R 经常看到各种乱码文字,让人看不懂意思,特别是在 Windows 系统上。
王诗翔呀
2020/07/02
1.8K0
CMD批处理——forfiles命令使用,自动删除过期备份文件
公司服务器用来备份数据的硬盘过段时间就会被备份文件占满,弄得我老是要登录到服务器去手工删除那些老的文件,有时忘记了就会导致硬盘空间不足而无法备份。 因为只要保留最近几天的备份,如果可以做一个批处理让系统自动删除老备份文件就好了,但是Windows的命令行和Linux的Shell比起来功能差了很多,到底行不行我自己也不清楚。 于是上网查了一下各位大虾发的帖子,再经过自己的摸索和尝试,发现只要花点功夫还是能实现这个功能的。 Windows Server 2003内置的命令行文件,适合于XP以上系统 示例:
landv
2018/05/24
4.4K0
点击加载更多

相似问题

找不到AngularJS映像取消显示错误

11

删除文件夹时出现forfiles错误

313

Forfiles -排序文件

20

Output forfiles错误到变量

04

找不到P4取消搁置文件错误

14
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文