同步问题

时间:2011-04-16 19:50:39

标签: java

我有以下示例代码,

public class test implements Runnable{

  public void run()
  {
    synchronized(this)
    {
        for(int i=0;i<10000;i++)
            System.out.println(i);
    }
  }
  public static void main(String args[]) throws Exception
  {
    Thread t=new Thread(new test());
    t.start();

    //Thread.sleep(100);
    t.suspend();
    System.out.println("Hi");
  }
}

我有以下要求,当线程被挂起时,它必须执行循环的所有迭代而不会被挂起。我觉得同步是为了这个目的,但它没有解决问题。当我挂起一个线程(如果它在同步块中)时,它必须在块执行后才被挂起。可以使用什么java构造?

2 个答案:

答案 0 :(得分:0)

在Java中,当一段代码在synchronized块中时,只有一个线程可以一次执行该块。为了在线程完成其同步块之后暂停线程,只需在同一个变量上同步:

public class Test implements Runnable {
    public void run() {
        synchronized(this) { 
            // some work
        }
    }

    public static void main(String args[]) throws Exception {
        Test target = new Test();
        Thread t = new Thread(target);
        t.start();

        synchronized(target) {
            t.suspend();
        }
        System.out.println("Hi");
    }
}

请注意,run()main()中的两个块都在同一个变量(Test的实例)上同步。现在main()中同步块中的代码只有在run()中的工作完成后才会执行。

(但请注意,这里存在一些竞争条件:t.start()之后run()中的代码将在main()中的下一行代码之前实际执行后,您无法保证

答案 1 :(得分:0)

suspend()暂停线程的执行权。从程序代码执行此操作通常不是一个好主意,因为该线程仍将保留任何监视器,锁,资源等。

相反,使用在您不希望执行时阻止该线程的同步原语。例如,信号量可用于使线程等待:

public class test implements Runnable{

final Semaphore semaphore = new Semaphore();

public void run()
{
    synchronized(this)
    {
        for(int i=0;i<10000;i++)
            System.out.println(i);
        semaphore.acquire();   // possibly block on the semaphore
        semaphore.release();   // release our lock, we don't need it anymore
    }    
}

public void suspend()
{
   semaphore.acquire();
}

public void resume()
{
   semaphore.release();
}
}

public static void main(String args[]) throws Exception
{
    Test test = new test());
    Thread thread = new Thread(test);
    thread.start();

    // at some point in the future you want to pause execution
    test.suspend();

    // hi will either appear before all of Test's output, or after. but not inbetween.
    System.out.println("Hi");

    test.resume();
}

您也可以使用Locks和Condition来实现相同的功能,但代码稍微多一点,所以我们在这里使用Semaphore来保持简单。

通过不直接挂起线程,而是阻塞它,你可以使用Executors,ThreadPools和其他类型的线程管理(例如ForkJoinPool,SwingWorker等)。