2017-06-06 86 views
1

我有一個簡單的程序用於兩個線程交替地打印增量數字。使用Java 8進行線程排序

所以, 第一線程打印:1個

第二個線程打印:2個

第一線程打印:3 ...等等

我能使用 '線' 類做這個。但我想看看如何使用Executor類來做到這一點。

用以下代碼.... executor類似乎不工作。任何指針?

代碼:

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

public class LocksPackagePractice { 

    private int i = 0; 

    ReentrantLock lock = new ReentrantLock(); 
    Condition condition = lock.newCondition(); 

    Runnable r =() -> { 
    for(int x = 0; x < 5; x++){ 
     printValue(); 
    } 
    printValue(); 
}; 

    public static void main(String[] args) { 

     new LocksPackagePractice().trigger(); 
    } 

    void trigger(){ 
     ExecutorService service = Executors.newFixedThreadPool(2); 
     service.execute(r); 
    } 

    void printValue(){ 

     lock.lock(); 

     try { 

      i++; 
      System.out.println(Thread.currentThread().getName() + " and value is = " + i); 

      condition.signal();   
      condition.await(); 

     } catch(InterruptedException e){ 
      e.printStackTrace(); 
     }finally { 
      lock.unlock(); 
     } 

    } 
} 
+1

您至少需要2個runnables(任務),以便執行程序可以使用不同的線程運行它們。此外,你需要一些任務之間的溝通方式(或讓他們產生新的子任務),以獲得你想要的行爲。不過,我強烈建議你深入挖掘線程和任務。讓2個線程按順序運行基本類似的任務會違背多線程的目的 - 就像綁定到特定線程的任務會違反線程池的目的一樣。 – Thomas

+0

謝謝托馬斯。 如果「有2個線程按順序運行一個基本類似的任務有違多線程的目的」....那麼Executor.newFixedThreadPool()和.execute(runnable)方法的用法是什麼? 我們是不是隻是通過不同的線程執行相同的runnable? – Deep

+1

'Executor.newFixedThreadPool()'是爲了提供一個固定的工作線程池,其中的任何一個都可以交給一個需要執行的任務。通過'Executor.execute(Runnable)',您可以將單個任務傳遞給執行程序,然後將該任務交給工作線程。基本思想是一個任務由一個線程執行。 – Thomas

回答

2

在製造程序中的一些變化。運行它並檢查它是否解決了混淆。

public class LocksPackagePractice { 
    private int i = 0; 
    ReentrantLock lock = new ReentrantLock(); 
    Condition condition = lock.newCondition(); 
    Runnable r =() -> { 
     printValue(); 
    }; 
    public static void main(String[] args) { 
     new LocksPackagePractice().trigger(); 
    } 
    void trigger() { 
     ExecutorService service = Executors.newFixedThreadPool(2); 
     service.submit(r); 
     for (int i = 0; i < 5; i++) { 
      service.execute(r); 
     } 
    } 
    void printValue() { 
     lock.lock(); 
     try { 
      i++; 
      System.out.println(Thread.currentThread().getName() + " and value is = " + i); 
      condition.signal(); 
      condition.await(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

這會給你下面的輸出

pool-1-thread-1 and value is = 1 
pool-1-thread-2 and value is = 2 
pool-1-thread-1 and value is = 3 
pool-1-thread-2 and value is = 4 
pool-1-thread-1 and value is = 5 
pool-1-thread-2 and value is = 6 
+0

你知道這是爲什麼卡在6嗎? – Deep

+1

是的!執行者必須被明確地停止 - 否則他們會不斷地收聽新的任務。您需要使用service.shutdown()方法關閉執行程序。我希望這有幫助。 –

+1

調用'shutdown()'不會起作用,因爲所有任務都掛在'condition.await()'末尾。 – Holger

0

我不知道,但你需要輸入訂貨?因爲你使用阻塞操作(鎖),並且在性能方面不好。

此代碼:

private AtomicInteger number = new AtomicInteger(0); 

    public static void main(String[] args) { 
    ExecutorService executor = Executors.newFixedThreadPool(2); 

    ForTestApplication testApplication = new ForTestApplication(); 

    for (int i = 0; i < 100; i++) { 
     executor.execute(testApplication::print); 
    } 

    } 

    public void print() { 
    System.out.println(Thread.currentThread().getName() + " : " + number.incrementAndGet()); 
    } 

使用AtomicInteger,而不是簡單的int值和鎖定操作。但是,輸出的順序可能是這樣的:

pool-1-thread-1 : 1 
pool-1-thread-2 : 2 
pool-1-thread-1 : 3 
pool-1-thread-1 : 4 
pool-1-thread-2 : 5 
pool-1-thread-2 : 7 
pool-1-thread-1 : 6 
pool-1-thread-2 : 8 
pool-1-thread-1 : 9 
pool-1-thread-2 : 10 

它你需要在你的輸出訂單,然後需要思考如何處理它。