2016-01-21 28 views
1

我一個單身有一個方法,一個字符串:只有在方法的時間

public void myMethod(String x){ 
    //do lengthy process on x 
} 

我有三個線程調用myMethod

  1. 線程A,X = 「字」 - >開始於05.00.01pm,於05.00.10pm結束
  2. 線程B,x =「句子」 - >在05.00.01pm開始,在05.00.08pm結束
  3. 線程C,x =「wor d「 - >從05.00.02pm開始,完成於???

,你可以看到,Thread C應該等到Thread A完成,因爲Thread C也發送word。然而,Thread B被允許在Thread A完成之前執行myMethod,因爲它發送的是sentence而不是word

myMethod將被頻繁調用,並有在myMethodparameter x沒有規則,所以我不認爲保存所有可能的值parameter x是可行的

FYI:而字符串長度「X」參數是不有限,字符保證只能是字母數字(a..zA..Z0..9),沒有奇怪的重音符 我該怎麼做?

+0

是否有從崑崙任何約束你的弦的帳篷?例如0-127範圍內的字符或整個Unicode? –

回答

1

您可以通過將根據您的字符串的規範表示一個synchronized塊的方法內實現這一

public void myMethod(String x){ 
    synchronized(x.intern()){ 
    //do lengthy process on x 
    } 
} 
+1

我不認爲字符串拘留是一個好主意。發送給myMethod的參數沒有規則,所以會有大量的字符串並會頻繁地觸發全局GC。 myMethod將被頻繁地調用 – Thomas

+0

如果它被頻繁調用,並且阻塞了一個簡單的進程,我認爲你的問題不會被串入。還要注意,在測量之前,您沒有性能問題。 –

+0

@JoaEbert如果他用字符串堆滿了字符串池,他可能會遇到內存問題。 – Tom

0

要確保你需要有作出鎖定的對象是一個HashMap,由鍵控功能參數:

Map<String,Object> locks=new HashMap<String,Object>(); 
public void myMethod(String x){ 
    Object lock; 
    synchronized (locks) { 
     if ((lock=locks.get(x)) == null) locks.put(x, lock = new Object()); 
    } 
    synchronized (lock) { 
     // do your staff 
    } 
} 

更新(測試):

private Map<String,Object> locks=new HashMap<String,Object>(); 

public void getLock(String x) { 
    for (;;) { 
     Object lock; 
     synchronized (locks) { 
      lock=locks.get(x); 
      if (lock == null) { 
       locks.put(x, lock=new Object()); 
       break; 
      } 
     } 
     try { 
      System.out.printf("Thread-%s locked\n",Thread.currentThread().getName()); 
      synchronized (lock) { 
       lock.wait(); 
      } 
     } catch (InterruptedException e) {} 
    } 
} 
public void unLock(String x) { 
    synchronized (locks) { 
     Object lock=locks.remove(x); 
     synchronized (lock) { 
      lock.notifyAll(); 
     } 
    }  
} 

public void myMethod(String x){ 
    getLock(x); 

    System.out.printf("Thread-%s start\n",Thread.currentThread().getName()); 
    // do your staff 
    for (int i=0; i<30; ++i) { 
     System.out.printf("Thread-%s running %d\n", Thread.currentThread().getName(),i); 
     try { 
      Thread.sleep(10); 
     } catch (InterruptedException e) {} 
    } 
    System.out.printf("Thread-%s end\n",Thread.currentThread().getName()); 

    unLock(x); 
} 

public void run() { 
    myMethod("abc"); 
} 

public static void main(String[] args) { 
    final Test t = new Test(); 
    Thread ths[] = new Thread[30]; 
    for (int i=0; i < ths.length; ++i) 
     ths[i]=new Thread(t, String.valueOf(i)); 

    for (int i=0; i < ths.length; ++i) 
     ths[i].start(); 
} 
+0

這看起來像是一個巨大的內存泄漏。 –

+0

是的,我剛剛意識到。思考.. :) – krzydyn

+0

我寫的第一個提交作爲一個快速的想法如何完成。更新版本正在工作 – krzydyn