-8

我想要一个在单独的线程中打印奇数和偶数的算法。输出应该是顺序的1,2,3.4 ,.....Executor 框架可以在这里使用。我在 SO 上看到了一个相关的问题,但那是在 C 中。我想要一个 Java 实现在这里。

4

7 回答 7

2

它是 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
于 2012-07-10T11:28:06.813 回答
1

您的问题有点令人困惑,因为看起来您希望按顺序输出。

在这种情况下使用线程是没有意义的,因为它们会不断地相互协调以确定轮到谁输出它们的当前数字。

如果您不关心排序(例如,您可能会得到 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);
    }
}
于 2012-07-10T11:21:16.770 回答
0
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");
}
于 2012-07-10T11:17:24.760 回答
0

一些忙等待的代码,最简单的。

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!");
    }

}
于 2012-07-10T15:43:57.127 回答
0
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();
        }
    }
}
于 2013-08-29T13:05:18.923 回答
0

/* 使用 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));

    }

}
于 2016-09-14T07:02:52.593 回答
0
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");

    }

}
于 2019-01-11T18:51:24.540 回答