Java:如何使用 Executor 框架从 2 个单独的线程中打印奇数和偶数
Posted
技术标签:
【中文标题】Java:如何使用 Executor 框架从 2 个单独的线程中打印奇数和偶数【英文标题】:Java: How to print odd and even numbers from 2 separate threads using Executor framework 【发布时间】:2012-07-09 20:17:27 【问题描述】:我想要一个在不同线程中打印奇数和偶数的算法。输出应该是顺序的1,2,3.4 ,.....
这里可以使用Executor框架。我见过 related question on SO 但那是在 C 中。我想要这里的 Java 实现。
【问题讨论】:
如果你必须像“结果应该是连续的”,那你就错了。 “线程”和“顺序”不能很好地结合在一起;线程在他们喜欢的时候运行得差不多了。考虑一下能够同时做两件事的代价——你放弃了对它们完成的确切以什么顺序的控制。如果你想让东西以特定的顺序运行,你必须做一些同步(阅读:使线程阻塞!)只是为了免费获得顺序处理给你的东西。 【参考方案1】:它是 jasons 的修改版:
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Test
public static void main(String[] args)
final int max = 100;
final AtomicInteger i = new AtomicInteger(0);
Executor dd = Executors.newFixedThreadPool(2);
final Object lock = new Object();
dd.execute(new Runnable()
@Override
public void run()
while (i.get() < max)
if (i.get() % 2 == 0)
System.out.print(" " + i.getAndAdd(1));
synchronized(lock)
lock.notify();
else
synchronized(lock)
try
lock.wait();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
);
dd.execute(new Runnable()
@Override
public void run()
while (i.get() < max)
if (i.get() % 2 != 0)
System.out.print(" " + i.getAndAdd(1));
synchronized(lock)
lock.notify();
else
synchronized(lock)
try
lock.wait();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
);
do
try
Thread.currentThread().sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
while (i.get() != max);
System.out.println("\nDone");
免责声明:它不是最好的解决方案,当然也不是最快的,但它会产生正确的输出。
这是输出:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Done
【讨论】:
【参考方案2】:您的问题有点令人困惑,因为您似乎希望按顺序输出。
在这种情况下使用线程是没有意义的,因为它们会不断地相互协调以确定轮到谁输出它们的当前数字。
如果您不关心排序(例如,您可能会得到 1、2、3、5、4、6、8.7...),那么它可能是有意义的。
public class Test
private static final int NOT_APPLICABLE = 1;
private final ExecutorService executor;
public Test()
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(2);
executor = new ThreadPoolExecutor(2, 2, NOT_APPLICABLE, TimeUnit.SECONDS, queue);
public void submitTask(Runnable task)
executor.submit(task);
private static class Counter implements Runnable
private int counter;
public Counter(int start)
this.counter = start;
@Override
public void run()
while (true)
System.out.println(counter);
counter += 2;
public static void main(String[] args)
Runnable odd = new Counter(1);
Runnable even = new Counter(2);
Test app = new Test();
app.submitTask(odd);
app.submitTask(even);
【讨论】:
如果是为了练习,没有理由要求在 *** 上提供现成的解决方案。 OP 应该阅读教程,并尝试一下。 添加了代码供您开始使用。请注意,当我运行它时,我得到了很多偶数,然后是很多赔率,然后是很多偶数。【参考方案3】:一些忙等待的代码,最简单的。
package t1;
import java.util.concurrent.atomic.AtomicInteger;
public class Redx implements Runnable
private final static int MAX = 99;
final AtomicInteger next;
final int odd;
public Redx(AtomicInteger next, int odd)
super();
this.next = next;
this.odd = odd;
public void run()
for(;;)
int n = next.get();
if (n > MAX)
break;
if ((n&1)==odd)
continue;
System.out.print(n+", ");
if ((n & 0x1F)==0x1F)//new line can be skipped
System.out.println();
next.lazySet(n+1);
public static void main(String[] args)
final AtomicInteger next = new AtomicInteger(0);
Redx x0 = new Redx(next, 0);
Redx x1 = new Redx(next, 1);
new Thread(x0).start();
new Thread(x1).start();
for(;next.get()<=MAX;)
Thread.yield();
System.out.println();
System.out.println("Done!");
【讨论】:
【参考方案4】:public static void main(String[] args)
final int max = 100;
final AtomicInteger i = new AtomicInteger(0);
new Thread(new Runnable()
@Override
public void run()
while (i.get() < max)
if (i.get() % 2 != 0)
synchronized (i)
System.out.print(" " + i.getAndAdd(1));
).start();
new Thread(new Runnable()
@Override
public void run()
while (i.get() < max)
if (i.get() % 2 == 0)
synchronized (i)
System.out.print(" " + i.getAndAdd(1));
).start();
do
try
Thread.currentThread().sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
while (i.get() != max);
System.out.println("\nDone");
【讨论】:
这是我运行代码后得到的序列:0 2 1 3 5 4 6 8 7 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 36 37 38 39 40 41 49 50 51 52 53 54 50 51 52 58 59 60 61 62 63 64 65 64 62 64 69 70 72 71 73 74 74 74 74 79 79 79 79 70 82 81 83 85 84 86 88 87 89 91 90 92 93 94 95 96 98 97 99 抱歉,我已经更新了代码,现在在我的机器上运行良好。【参考方案5】:import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class GenerateEvenOddNumberTest
public static void main(String[] args)
GenerateNumber GenNum = new GenerateNumber();
ExecutorService es = Executors.newFixedThreadPool(2);
es.execute(GenNum);
es.execute(GenNum);
class GenerateNumber implements Runnable
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> count =
new ThreadLocal<Integer>()
@Override protected Integer initialValue()
return nextId.getAndIncrement();
;
private static final AtomicBoolean bool = new AtomicBoolean(true);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Boolean> even =
new ThreadLocal<Boolean>()
@Override protected Boolean initialValue()
return bool.getAndSet(false) ;
;
boolean isOdd = false;
Lock lock = new ReentrantLock();
Condition checkOdd = lock.newCondition();
Condition checkEven = lock.newCondition();
public void printEvenNumber()
lock.lock();
try
while(count.get()<500)
while(isOdd)
try
checkEven.await();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Thread Name "+Thread.currentThread().getName()+" "+count.get());
count.set(count.get()+2);
isOdd = true;
checkOdd.signal();
finally
lock.unlock();
public void printOddNumber()
lock.lock();
try
while(count.get()<500)
while(!isOdd)
try
checkOdd.await();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Thread Name "+Thread.currentThread().getName()+" "+count.get());
count.set(count.get()+2);
isOdd = false;
checkEven.signal();
finally
lock.unlock();
@Override
public void run()
if(even.get())
printEvenNumber();
else
printOddNumber();
【讨论】:
【参考方案6】:/* 使用 Semaphore 是打印奇偶数列的最简单方法 */
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
class Even implements Runnable
private Semaphore s1;
private Semaphore s2;
private static volatile int num = 0;
Even(Semaphore s1, Semaphore s2)
this.s1 = s1;
this.s2 = s2;
@Override
public void run()
synchronized (s2)
while (num < 99)
try
s1.acquire();
System.out.print(" " + num);
num += 2;
s2.release();
catch (InterruptedException e)
e.printStackTrace();
class Odd implements Runnable
private Semaphore s1;
private Semaphore s2;
private static volatile int num = 1;
Odd(Semaphore s1, Semaphore s2)
this.s1 = s1;
this.s2 = s2;
@Override
public void run()
synchronized (s1)
while (num < 100)
try
s2.acquire();
System.out.print(" " + num);
num += 2;
s1.release();
catch (InterruptedException e)
e.printStackTrace();
public class ExecOddEvenPrint
public static void main(String[] args)
ExecutorService exec = Executors.newFixedThreadPool(2);
Semaphore s1 = new Semaphore(1);
Semaphore s2 = new Semaphore(0);
exec.execute(new Even(s1, s2));
exec.execute(new Odd(s1, s2));
【讨论】:
【参考方案7】:This will do:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Threads implements Runnable
static AtomicInteger x=new AtomicInteger(1);
public void generate()
//System.out.println("In generate");
synchronized(x)
if(x.get()%2==0)
System.out.println(x+" is EVEN");
else
System.out.println(x+" is ODD");
x.incrementAndGet();
@Override
public synchronized void run()
//System.out.println("In run");
generate();
public static void main(String[] args)
//System.out.println("In generateThreads");
ExecutorService pool=Executors.newFixedThreadPool(10);
for(int i=0;i<2;i++) // two threads
pool.submit(new Threads());
pool.shutdown();
while (!pool.isTerminated())
// System.out.println("DONEs");
【讨论】:
以上是关于Java:如何使用 Executor 框架从 2 个单独的线程中打印奇数和偶数的主要内容,如果未能解决你的问题,请参考以下文章