我制作了这个简单的线程减法程序。 它工作正常但在输出结束时它提供3个随机值。我不知道如何预防,任何想法? 我还要计算每个线程减少我的计数器的次数。有人可以帮我这个吗?
public class ThreadsExample implements Runnable {
static int counter = 100000;
static long time;
static long endtime;
static float finaltime;
static int value;
static void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter--;
}
@Override
public void run() {
time = System.nanoTime();
while (counter >= 0) {
incrementCounter();
}
endtime = System.nanoTime() - time;
finaltime = endtime;
System.out.println(finaltime / 1000000000 + " sekundy");
}
public static void main(String[] args) throws InterruptedException {
ThreadsExample threads = new ThreadsExample();
Thread thread1 = new Thread(threads);
Thread thread2 = new Thread(threads);
Thread thread3 = new Thread(threads);
Thread thread4 = new Thread(threads);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
if (counter <= 0) {
System.out.println("Thread 1,2,3,4^^^");
}
}
}
答案 0 :(得分:0)
您遇到了多线程编程的缺陷。 您可能遇到两个问题。
counter
声明为volatile,因此访问它的线程可能不会立即看到它的当前值counter >= 0
可能是真的,然后线程2递减计数器,然后线程1也减少它,因为它认为计数器&gt; = 0。结帐java.util.concurrent.atomic.AtomicInteger
。
您可能希望将其用作counter
。
答案 1 :(得分:0)
如果我理解您的问题,请尝试进行一些调整:
// Need to import Lock to protect synchronized logic
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadsExample implements Runnable {
static int counter = 100000;
// Lock to help synchronize access to counter
static Lock lock = new ReentrantLock();
// These should not be static - they should be local to each ThreadsExample
long time;
long endtime;
float finaltime;
// Didn't see where this was used, so I'm using to track mod count
int value;
// Doesn't need to be static
void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter--;
}
@Override
public void run() {
time = System.nanoTime();
// Use this boolean to determine when to stop
boolean done = false;
while (!done) {
// Acquire the lock
lock.lock();
try {
// Now that this thread owns the lock, it can check
// the counter without worrying about other threads
// making modifications
if (counter > 0) {
incrementCounter();
// Increment the mod count (how many times this thread affected counter)
value++;
} else {
// We can stop here since counter is 0 or less
done = true;
}
} finally {
// Release the lock so other threads have a chance
lock.unlock();
}
}
endtime = System.nanoTime() - time;
finaltime = endtime;
System.out.println(finaltime / 1000000000 + " sekundy");
// Print out the mod count
System.out.println(Thread.currentThread().getName() + " updated counter " + value + " times.");
}
public static void main(String[] args) throws InterruptedException {
// Create a new ThreadsExample for each Thread
// And give the threads readable names.
Thread thread1 = new Thread(new ThreadsExample(), "thread-1");
Thread thread2 = new Thread(new ThreadsExample(), "thread-2");
Thread thread3 = new Thread(new ThreadsExample(), "thread-3");
Thread thread4 = new Thread(new ThreadsExample(), "thread-4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
// Note: This will likely never get printed since it might take
// a few milliseconds for the other threads to "consume" the counter
if (counter <= 0) {
System.out.println("Thread 1,2,3,4^^^");
}
}
}
我还建议给ThreadsExample一个本地名称变量,而不是使用Thread.currentThread()。getName(),但这取决于你。
答案 2 :(得分:0)
public class ThreadsExample implements Runnable {
private static volatile int counter = 100000; // 10k
private int counterDecrements = 0; // zero decrements
// Doesn't need to be static, but should likely be synchronized
private void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter);
// counter--;
// ++counterDecrements;
}
@Override
public void run() {
long startTime, endTime, timeDiff;
startTime = System.currentTimeMillis();
while (counter >= 0) {
incrementCounter(); // thread loop
--counter;
++counterDecrements;
}
endTime = System.currentTimeMillis();
timeDiff = startTime - endTime; // time diffrence is how long it took.
System.out.println((timeDiff / 1000000000) + " sekundy");
// Print out the mod count
System.out.println(Thread.currentThread().getName() + " Decremented counter " + counterDecrements + " times.");
}
public static void main(String[] args) throws InterruptedException {
// Create a new ThreadsExample for each Thread
// And give the threads readable names.
Thread thread1 = new Thread(new ThreadsExample(), "thread-1");
Thread thread2 = new Thread(new ThreadsExample(), "thread-2");
Thread thread3 = new Thread(new ThreadsExample(), "thread-3");
Thread thread4 = new Thread(new ThreadsExample(), "thread-4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
if (counter == 0) {
System.out.println("Thread 1,2,3,4^^^^");
}
}
}