[英]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.