包含方法调用的synchronized块,这会有效吗?

时间:2012-08-05 19:55:56

标签: android arrays synchronization handler runnable

以下代码是否合法用于同步myIntArray?
它会阻止三种底层方法无法更改myIntArray吗? 我希望事情按照delayedMethod1,delayedMethod2,method3的顺序发生,并且在上一个完成对myIntArray的更改之前没有通过运行来搞砸其中一个。
底部3方法声明是否需要同步关键字?
底部的3个方法是否需要包含synchronized(myIntArray)块? 我的同步块应该在Runnable周围而不是在它内部吗? 我是否需要通知,等待或加入命令?

            public class HelpPlease {

                public int myIntArray[] = new int[100];

                public void chooseSquare() {

                    ...
                    Handler handler=new Handler();
                    final Runnable r = new Runnable()
                    {
                        public void run() 
                        {   
                            synchronized(myIntArray) {
                                delayedMethod1();
                            }
                        }
                    };
                    handler.postDelayed(r, 1000);

                    ...

                    Handler handler2=new Handler();
                    final Runnable r2 = new Runnable()
                    {
                        public void run() 
                        {    
                            synchronized(myIntArray) {
                                delayedMethod2();
                            }
                        }
                    };
                    handler2.postDelayed(r2, 1000);

                    ...

                    synchronized(myIntArray) {
                        method3();
                    }
               }

               public void delayedMethod1() {
                    ...
                    change myIntArray;
                    otherMethodsABC();
               {

               public void delayedMethod2() {
                    ...
                    change myIntArray;
                    otherMethodsDEF();
               }

               public void method3() {
                    ...
                    change myIntArray;
                    otherMethodsGHI();
               }
           }

更多详情:Handler/Runnable delays producing events that are out of sync sometimes

编辑:

这有意义吗?运行一个线程等待它完成?不知道如何添加延迟,这就是重点。

                        //Handler handler=new Handler();
                        final Runnable r = new Runnable()
                        {
                            public void run() 
                            {
                                delayedMethod();
                            }
                        };
                        //handler.postDelayed(r, COMPUTER_MOVE_DELAY);

                        ExecutorService es = Executors.newFixedThreadPool(1);

                        final Future f1 = es.submit(r);

                        try
                           {
                               f1.get();
                           }
                           catch (InterruptedException e)
                           {
                               throw new RuntimeException(e);
                           }
                           catch (ExecutionException e)
                           {
                               throw new RuntimeException(e);
                           }

1 个答案:

答案 0 :(得分:0)

不要尝试使用synchronized块执行此操作。它只能保证没有两个块同时运行 ,而不是它们运行的​​顺序。你最好写一个“父”runnable,按你想要的顺序执行延迟的方法。或者,你可以使用第一种方法,一旦完成,发布一个runnable来运行第二种方法等,将它们链接在一起。

更具体地说,如果你想延迟然后三个方法按顺序运行,我会像这样编码:

public class HelpPlease {
    public int myIntArray[] = new int[100];
    Handler handler=new Handler();

    public void chooseSquare() {
        ...
        final Runnable r = new Runnable()
        {
            public void run() 
            {
                delayedMethod1();
                delayedMethod2();
                method3();
            }
        };
        handler.postDelayed(r, 1000);
    }

    public void delayedMethod1() {
        ...
        change myIntArray;
        otherMethodsABC();
    }

    public void delayedMethod2() {
        ...
        change myIntArray;
        otherMethodsDEF();
    }

    public void method3() {
        ...
        change myIntArray;
        otherMethodsGHI();
    }
}

根本不需要同步。使用单个Handler来保证对chooseSquare()的多次调用将导致可运行的序列化执行非常重要。

编辑:

根据您的最新评论,以下是我的进展方式。首先,拥有一个Handler对象,您可以通过所有操作计划代码访问该对象。要使用这两个示例,可以按如下方式实现:

public void chooseSquare() {
    . . .
    if (point_scored) {
        makeSquaresGlow(list_of_squares);
        playSound(sound_to_play);
        handler.postDelayed(new Runnable() {
            public void run() {
                makeSquaresNotGlow(list_of_squares);
            }
        }, 1000L);
    }
    if (time_for_attack(purple)) {
        handler.postDelayed(new Runnable() {
            public void run() {
                launchAttack(purple);
            }
        }, 1000L);
    }
}

假设在事件线程上调用了chooseSquare(),所有内容(包括延迟方法调用)也将在同一个线程上运行,因此不需要同步。可能存在竞争条件(launchAttackmakeSquaresNotGlow将同时安排),但handler将一次执行一个竞争条件。如果这些延迟动作的排序至关重要,您可以定义一个“元”动作Runnable,它接受​​一系列动作并在将来按照规定的顺序执行它们。