2011-04-16 80 views
0

我有下面的代码试样片,问题的同步

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结构可以用于这个?

+0

注意的可能性Thread.suspend ()已被弃用。 http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#suspend() – 3urdoch 2011-04-16 19:52:44

回答

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()下一行之前执行)

+0

虽然这确实起作用,但为并发控制挂起线程并不是很好的线程化设计,而且天生就容易出现僵局。请参阅http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html – mdma 2011-04-16 20:19:30

+0

@mdma我同意这很糟糕。我不想质疑设计,而是提供一个可行的解决方案。 – pajton 2011-04-16 20:24:07

+0

当然,我自己做了几次同样的事!只是想让OP在生产系统中使用Thread.suspend()的时候意识到这一点。 – mdma 2011-04-16 20:27:05

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(); 
} 

您还可以使用锁和Condition来达到同样的事情,但它稍微是更多的代码,所以我们用信号灯的位置,以保持它的简单。

通过不直接挂起线程,但阻止它,而不是,你打开使用执行人,线程池和其他类型的线程管理(例如ForkJoinPool,SwingWorker类等)