1

场景:

  1. 我有一个包含 15 个索引的整数数组。(每个都填充了一些值)
  2. 我希望两个线程将两个(+2)添加到索引的值。每个人都知道已经添加了哪个索引。
  3. 然后加入线程并退出。

到目前为止(到我做它的地方)我只是实现了 Runnable 接口并将数组提供给 runnable 内部的计算。我不知道如何从这里进行握手。在此先感谢您的帮助

public class FooRunnable implements Runnable
{
    private int[] myArray = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};

    @Override
    public void run()
    {
        for(int i=0; i<myArray.length; i++)
        {
            myArray[i] = myArray[i] +2;
            System.out.println("Thread "+Thread.currentThread().getName()+" Finished index: "+i);
            atomicCount.incrementAndGet();
        }
    }

    public static void main(String[] args)
    {
        FooRunnable r = new FooRunnable();
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        t1.setName("Thread One");
        t2.setName("Thread Two");
        t1.start();
        t2.start();
    }
}

结果(目标):

当程序退出时。数组应该通过两个不同的线程使数组的每个元素增加 2。

4

4 回答 4

2

这行不通。线程一有可能与线程二同时读取 myArray[0]。然后两个线程都加 2。您必须在数组中同步或使用 AtomicIntegers。我认为这是某种练习。你想要完成什么?

于 2013-03-02T21:57:03.453 回答
1

您的代码必须是synchronized. 这需要两个线程之间进行适当的线程间通信,以增加后续索引处的值。虽然这可以通过使用wait和的旧方法来实现notify。但现在你应该切换到java.util.concurrent包。代码看起来像这样:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Foo
{
    private int[] myArray = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};//This array can be of any length.
    private volatile int lastIndex = 0;
    private final Lock lock = new ReentrantLock(true);
    private final Condition condition = lock.newCondition();
    public void increment()
    {
        lock.lock();
        try
        {
            if (isDone())
            {
                return;
            }
            myArray[lastIndex] = myArray[lastIndex]+2;
            System.out.println("Incremented arr["+lastIndex+"] to "+myArray[lastIndex]+" via thread "+Thread.currentThread().getName());
            lastIndex++;
            condition.signal();
            if (!isDone())
            {
                condition.await();
            }
        }
        catch (Exception ex){}
        finally{lock.unlock();}
    }

    public boolean isDone()
    {
        return lastIndex == myArray.length;
    }
    public static void main(String[] args)
    {
       final Foo foo = new Foo();
       Thread th1 = new Thread("Thread1")
        {
           public void run()
            {
               while (!foo.isDone())
               {
                    foo.increment();
               }
            }
        };
        Thread th2 = new Thread("Thread2")
        {
            public void run()
            {
                while (!foo.isDone())
                {
                    foo.increment();
                }
            }
        };
        th2.start();th1.start();
    }
}
于 2013-03-02T22:37:32.550 回答
1

您可以使用整数对象同步整数访问。而且,每当一个线程想要增加一个整数时,它应该检查该整数之前是否已经增加,方法是检查if(myArray[i].intVal() == i)this 是否返回 false ,然后另一个线程已经增加了这个整数。需要注意的是,增量之前的整数值等于索引,在这种情况下,i。

public class FooRunnable implements Runnable
{
    private Integer[] myArray = {new Integer(0),new Integer(1),new Integer(2),new Integer(3),new Integer(4),new Integer(5),new Integer(6),new Integer(7),new Integer(8),new Integer(9),new Integer(10),new Integer(11),new Integer(12),new Integer(13),new Integer(14)};

    @Override
    public void run()
    {
        for(int i=0; i<myArray.length; i++)
        {
            synchronized(myArray[i]) {
            if(myArray[i].intVal() == i) {
            myArray[i] = myArray[i] +2;
            System.out.println("Thread "+Thread.currentThread().getName()+" Finished index: "+i); }
             }
            atomicCount.incrementAndGet();
        }
    }

    public static void main(String[] args)
    {
        FooRunnable r = new FooRunnable();
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        t1.setName("Thread One");
        t2.setName("Thread Two");
        t1.start();
        t2.start();
    }
}
于 2013-03-02T22:32:24.420 回答
1

而且 - 当然 - 还有其他使用 Atomics 的方法:

public class FooRunnable implements Runnable {

    private int[] myArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
    // Copy myArray into my Atomic version.
    private AtomicInteger[] myAtomicArray = new AtomicInteger[myArray.length];
    {
        for(int i = 0; i < myArray.length; i++ ) {
            myAtomicArray[i] = new AtomicInteger(myArray[i]);
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < myArray.length; i++) {
            myAtomicArray[i].addAndGet(2);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        FooRunnable r = new FooRunnable();
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        t1.setName("Thread One");
        t2.setName("Thread Two");
        t1.start();
        t2.start();
        // Wait for them both to finish.
        t1.join();
        t2.join();
        // Print my results.
        System.out.println("Results: "+Arrays.toString(r.myAtomicArray));
    }
}

哪个打印

Results: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
于 2013-03-02T23:51:47.297 回答