简单的MultiThreads程序错误输出

时间:2017-05-27 16:42:32

标签: java multithreading

我制作了这个简单的线程减法程序。 它工作正常但在输出结束时它提供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^^^");
        }
    }
}

3 个答案:

答案 0 :(得分:0)

您遇到了多线程编程的缺陷。 您可能遇到两个问题。

  1. 您没有将counter声明为volatile,因此访问它的线程可能不会立即看到它的当前值
  2. 您没有根据条件进行原子更新(即计数器&gt; = 0)。 你对线程1的检查counter >= 0可能是真的,然后线程2递减计数器,然后线程1也减少它,因为它认为计数器&gt; = 0。
  3. 结帐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^^^^");
        }
    }
}