使用Java 8进行线程排序

问题描述:

我有一个简单的程序用于两个线程交替地打印增量数字。使用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

在制造程序中的一些变化。运行它并检查它是否解决了混淆。

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

我不知道,但你需要输入订货?因为你使用阻塞操作(锁),并且在性能方面不好。

此代码:

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 

它你需要在你的输出订单,然后需要思考如何处理它。