同步块内的Thread.sleep导致另一个Thread不应该等待

时间:2014-02-06 18:10:42

标签: java android multithreading concurrency

我有这个简单的线程:

aQueueThread = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        while(!Thread.interrupted())
                        {
                            QueueElementWrapper wrapper = aRequestsQueue.take();

                            Thread.sleep(2000);
                            synchronized(aQueueLock)
                            {
//                              Thread.sleep(2000);
                                aMainExecutor.submit(wrapper.aCallable);

                                if(wrapper.aRequestType == EQueueElementType.RELOGIN)
                                    aQueueLock.wait();
                            }
                        }
                    }
                    catch(InterruptedException ie)
                    {
                    }
                    finally
                    {
                    }
                }
            }, "DownloaderThread");
            aQueueThread.setDaemon(true);
            aQueueThread.start();

运行循环中有一个LinkedBlockingDeque(即aRequestsQueue引用)。

现在,我在MainThread中运行另一个方法,该方法也使用基于aQueueLock的synchronized块。当我在synchronized块之外使用Thread.sleep()方法时,一切都很好。一旦这个方法离开它的同步blo,MainThread就会启动但是,如果我将它移动2行,那么它将在sychronized块内,由于某种原因,MainThread正在等待,直到aRequestsQueue内部没有更多元素,直到它被允许输入其他方法同步块。

任何人都可以为我解开这个谜团吗?

//修改

好的,为了排除我复杂代码中的原因,我快速地写了一个测试代码。使用单个Activity创建了一个空的android项目。我在主要布局中添加了一个白色的200x200视图:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <View
        android:id="@+id/view" 
        android:layout_width="200dip"
        android:layout_height="200dip"
        android:background="@android:color/white"
        android:visibility="invisible"
        />

</RelativeLayout>

修改了MainActivity以更改此视图的可见性,如下所示:

public class MainActivity extends Activity
{

    Object lockObject = new Object();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Thread thread = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    for(int i = 0 ; i < 5 ; i++)
                    {
//                      Thread.sleep(2000);
                        synchronized(lockObject)
                        {
                            Thread.sleep(2000);
                        }
                    }
                } 
                catch (InterruptedException e1)
                {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });

        thread.setDaemon(true);
        thread.start();

        new CountDownTimer(4000, 4000)
        {

            @Override
            public void onTick(long millisUntilFinished)
            {
            }

            @Override
            public void onFinish()
            {
                synchronized(lockObject)
                {
                    findViewById(R.id.view).setVisibility(View.VISIBLE);
                }
            }
        }.start();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

我认为它不会比这更简单。如果将sleep()调用保留在synchronized块内,则在10秒后出现白色方块。如果您评论那个,并将其留在同步块之外,您将在4秒后看到白色方块。

0 个答案:

没有答案