递增变量多线程

时间:2018-07-11 11:18:30

标签: java multithreading

假设我有10个线程将变量加1。假设线程1首先增加变量,然后线程2和线程3依次增加。在所有10个线程都增加了变量之后。我需要以某种方式减少相同的变量。

递减,如果Thread-1首先使变量递增,那么它最后应递减。

我们需要在不设置线程优先级的情况下执行此操作。

2 个答案:

答案 0 :(得分:1)

这似乎有效。本质上,我创建了10线程,并使用enum专门标识了其中之一。他们都尝试增加共享整数,以标识自己。增量器通过注意到过渡到1来检测第一个增量,如果它是Special线程,则返回true

还有一个CountDownLatch用于同步所有线程,以确保至少有两种选择的机会。我从8600首先到达那里的10000测试中获得了Special。该值将取决于许多变量。

enum Who {
    Special, Normal;
}

class PriorityIncrementer {
    final AtomicInteger i = new AtomicInteger(0);

    boolean inc(Who who) {
        return i.incrementAndGet() == 1 && who == Who.Special;
    }

    public void dec() {
        i.decrementAndGet();
    }
}

class TestRunnable implements Runnable {
    final Who me;
    final PriorityIncrementer incrementer;
    final CountDownLatch latch;

    public TestRunnable(PriorityIncrementer incrementer, CountDownLatch latch, Who me) {
        this.incrementer = incrementer;
        this.latch = latch;
        this.me = me;
    }

    @Override
    public void run() {
        // Wait for all others to get here.
        latch.countDown();
        try {
            // Wait here until everyone os waiting here.
            latch.await();
            // Do it.
            if(incrementer.inc(me)) {
                // I was first and special, decrement after.
                incrementer.dec();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private boolean test(int count) throws InterruptedException {
    Thread[] threads = new Thread[count];
    // The shared incrementer.
    PriorityIncrementer incrementer = new PriorityIncrementer();
    // Arrange for all of them to synchronise.
    CountDownLatch latch = new CountDownLatch(threads.length+1);
    // One special.
    threads[0] = new Thread(new TestRunnable(incrementer, latch, Who.Special));
    // The rest are normal.
    for(int i = 1; i < threads.length; i++) {
        threads[i] = new Thread(new TestRunnable(incrementer, latch, Who.Normal));
    }
    // Start them up.
    for (Thread thread : threads) {
        thread.start();
    }
    // Wait a moment.
    Thread.sleep(1);
    // Start them all going.
    latch.countDown();
    // Wait for them to finish.
    for (Thread thread : threads) {
        thread.join();
    }
    // Who won?
    return incrementer.i.get() < count;
}

public void test() throws InterruptedException {
    final int tests = 10000;
    int specialWasFirstCount = 0;
    for (int i = 0; i < tests; i++) {
        if(test(10)) {
            specialWasFirstCount += 1;
        }
    }
    System.out.println("Specials: "+specialWasFirstCount+"/"+tests);
}

答案 1 :(得分:1)

您可以使用很多方法,例如:

public class Main {
    public static void main(String[] args) throws Exception {
        for(int i=0;i<10;i++){
            final int _i=i;
            Thread t = new Thread(new T(_i));
            t.start();
      }
    }
    public static class T implements Runnable{
        int threadNumber;
        public T(int threadNumber) {
            this.threadNumber=threadNumber;
        }

        @Override
        public void run() {
            increase(this);
        }
    }
    static Thread[] threads = new Thread[10];
    static int number  =0;
    static Object generalLock=new Object();
    public static void increase(T t){
        int myNumber=0;
        synchronized (generalLock){
            myNumber=number;
            System.out.println("i am "+number+" incrementing, my real number "+t.threadNumber);
            threads[number]=Thread.currentThread();
            number++;
        }
        while (threads[9]==null){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=9;i>myNumber;i--){
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        synchronized (generalLock){
            System.out.println("i am "+number+" decrementing, my real number "+t.threadNumber);
            number--;
        }
    }
}

输出示例:

i am 0 incrementing, my real number 1
i am 1 incrementing, my real number 8
i am 2 incrementing, my real number 9
i am 3 incrementing, my real number 7
i am 4 incrementing, my real number 6
i am 5 incrementing, my real number 5
i am 6 incrementing, my real number 0
i am 7 incrementing, my real number 4
i am 8 incrementing, my real number 3
i am 9 incrementing, my real number 2
i am 9 decrementing, my real number 2
i am 8 decrementing, my real number 3
i am 7 decrementing, my real number 4
i am 6 decrementing, my real number 0
i am 5 decrementing, my real number 5
i am 4 decrementing, my real number 6
i am 3 decrementing, my real number 7
i am 2 decrementing, my real number 9
i am 1 decrementing, my real number 8
i am 0 decrementing, my real number 1

注意:您可以使用简单的Runnable,我创建T类来显示线程号,以便在递增/递减时打印它