简体   繁体   English

服务(Android)中的竞争状况(线程过多)

[英]Race condition in the Service(Android) (Too many threads)

I don't know why, but this function is going in the loop under Timer, user specifies how long he wants to wait in between the updates. 我不知道为什么,但是此函数在Timer下的循环中进行,用户指定在更新之间要等待多长时间。 Somehow the function halts (hangs) on the part, where "System.out.println("checking to add a new comment");". 该函数以某种方式暂停(挂起)在零件上,其中为“ System.out.println(“正在检查以添加新注释”);“。 The interesting thing is that this code runs few times before the whole application freezes, so it doesn't have any errors 有趣的是,此代码在整个应用程序冻结之前运行了几次,因此它没有任何错误

public ArrayList<String> newComments = new ArrayList<String>();
private ArrayList<String> downloadedComments = new ArrayList<String>();

 onStart(){
    if (receivedComments != null) {fthread
                for (int i = 0; i < receivedComments.size(); i++) {
                    if (newComments.contains(receivedComments.get(i))) {
                        System.out.println("Contains.");
                        newComments.remove(receivedComments.get(i));
                    }
                }
            }
    }

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        System.out.println("got msg");
        switch (msg.what) {
        case 1:
            int add = 0;
            System.out.println("start filling the comments");
            for (int i = 1; i < comments.size(); i++) {
                newComment = comments.get(i).text();
                // System.out.println(newComment);
                System.out.println("checking to add a new comment");
                if (!downloadedComments.contains(newComment)) {
                    newComments.add(newComment);
                    System.out.println("additing");
                    downloadedComments.add(newComment);
                    System.out.println("added");
                    add++;
                    // System.out.println("New comments");
                    // System.out.println(newComments);
                }
                // downloadedComments.add(newComment);
            }

            // System.out.println(add);

            break;

        case 2:
            System.out.println("time refresh");
            timeUpdate.scheduleAtFixedRate(new UpdateGui(context,
                    appWidgetManager), 1, 3000);
        }
    }
};

UpdateGUI class UpdateGUI类

private class UpdateGui extends TimerTask {
        Context context;

        public UpdateGui(Context context, AppWidgetManager appWidgetManager) {
            this.context = context;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (true) {
                for (int i = 0; i < newComments.size(); i++) {
                    try {
                        System.out.println("sleeping");
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    if (newComments.size() > 0) {
                        notificationView.setViewVisibility(
                                R.id.widget_notificationtext,
                                LinearLayout.VISIBLE);
                        notificationView.setTextViewText(
                                R.id.widget_notificationtext,
                                String.valueOf(newComments.size()));
                    } else {
                        notificationView.setViewVisibility(
                                R.id.widget_notificationtext,
                                LinearLayout.INVISIBLE);
                    }
                    if (newComments.size() != 0) {
                        remoteViews.setTextViewText(R.id.widget_text,
                                newComments.get(i));
                    } else {
                        remoteViews.setTextViewText(R.id.widget_text,
                                "No unread comments");
                    }
                    appWidgetManager.updateAppWidget(thisWidget, remoteViews);
                    appWidgetManager.updateAppWidget(thisWidget,
                            notificationView);
                }
try {
                        System.out.println("sleeping");
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            }
        }

    }

Since I am waiting every time 3 seconds to update my GUI from the thread, i did not consider what to do when there is nothing to update it with, so the code is being executed at once, but now i added a three seconds delay there as well and everything works just fine. 由于我每次等待3秒从线程更新我的GUI,所以我没有考虑什么也没更新时要做什么,因此代码立即被执行,但是现在我在那儿增加了三秒钟的延迟以及一切正常。 I know that this is not the best design of the application, but i could not come up with anything more eficient than this for now. 我知道这不是应用程序的最佳设计,但是到目前为止,我无法提出比这更有效的方法。 This was a typical race condition during the update when there is nothing to update, so a simple sleep would help 这是更新期间的典型竞赛条件,没有任何更新,因此简单的睡眠会有所帮助

I'd bet a good amount that this is basically a race condition issue. 我敢打赌,这基本上是一个种族问题。 You are using a bunch of different threads (UI, Timer, Handler, and possibly more). 您正在使用许多不同的线程(UI,计时器,处理程序,可能还有更多)。 ArrayList is not a synchronized or thread safe class, which means that it's entirely possible that downloadedComments is getting updated while at the same time .contains() is running, causing the internal loop to run basically forever. ArrayList不是同步的或线程安全的类,这意味着完全有可能在运行.contains()的同时更新downloadedComments ,从而导致内部循环基本上永远运行。 If you are not passing the data to the various targets (thus ensuring that nothing is being modified in two places), you will have to wrap the accesses in synchronized blocks to prevent concurrent access. 如果您没有将数据传递给各个目标(因此请确保两个地方都没有修改),则必须将访问包装在synchronized块中,以防止并发访问。

Note that you can get a synchronized version of the list thus: 请注意,您可以这样获得列表的同步版本:

List list = Collections.synchronizedList(new ArrayList(...));

Synchronization of every method has performance implications. 每种方法的同步都会影响性能。 That may not matter for you, though. 不过,这对您可能并不重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM