簡體   English   中英

遞增變量多線程

[英]Incrementing variable multi-threading

假設我有10個線程將變量遞增1。假設Thread-1首先遞增變量,然后依次是Thread-2和Thread-3。 在所有10個線程都增加了變量之后。 我需要以某種方式減少相同的變量。

遞減,如果Thread-1首先使變量遞增,則最后應遞減。

我們需要在不設置線程優先級的情況下執行此操作。

這似乎有效。 本質上,我創建了10線程,並使用enum專門標識了其中的一個。 他們都嘗試增加共享整數,以標識自己。 增量器通過注意過渡到1來檢測第一個增量,如果它是一個Special線程,則返回true

還有一個CountDownLatch用於同步所有線程,以確保至少有兩種選擇的機會。 Special首先到達的10000測試中,我得到了大約8600 該值將取決於許多變量而變化。

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

您可以使用多種方式,例如以下一種:

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類來顯示線程號,以便在遞增/遞減時打印它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM