0

行。我需要创建三个线程:一个获取奇数,一个获取偶数,一个将奇数和偶数相加。输出将是这样的(1,2,3,3,4,7...)。我是线程新手,仍然对它们的工作方式感到不安,但这是我到目前为止所拥有的:

class even extends Thread 
{
    public void even()
    {
        Thread ThreadEven = new Thread(this); 
        start(); 
    } 
    public void run() 
    {
        try
        {
            for(int i = 0; i < 10; i += 2) 
            {
                System.out.println(i);
            }
            Thread.sleep(1000);
        }
        catch(Exception e) 
        {
            System.out.println("Error: Thread Interrupted");
        } 
    } 
}

class odd extends Thread 
{ 
    public void odd() 
    {
        Thread ThreadOdd = new Thread(this); 
        start(); 
    } 
    public void run() 
    {
        try
        {
            for(int i = 1;i < 10; i += 2) 
            System.out.println(i);
            Thread.sleep(1000);
        }
        catch(Exception e) 
        {
            System.out.println("Error: Thread Interrupted");
        } 
    } 
}
class ThreadEvenOdd
{
    public static void main(String args []) 
    {
        even e = new even();
        odd o = new odd();

    } 
} 

这会打印出 0,2,4...然后是 1,3,5。如何交错?并交错我想要的东西,我也应该同步线程吗?我不明白的是如何将奇数和偶数线程的值放入三分之一以添加总和。如果我没有得到正确的代码格式,请事先道歉。

4

2 回答 2

1

如前所述,这是一个高级问题,是的,在尝试此操作之前,您应该阅读大量教程。即使对于这个简短的程序,如果我没有花费大量时间研究Java 并发实践,我也永远无法编写它。(提示 - 买这本书。它都在里面。)

偶数类和奇数类是生产者。类总和是消费者。生产者和消费者共享一个阻塞队列来传递数据。生产者使用负数作为毒丸表示他们已经完成并且不会有更多数据出现。当消费者检测到毒丸时,它会减少倒计时锁存器。主线程将此作为工作完成的信号。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;


public class OddEven
{
   public static void main(String [] args) throws InterruptedException
   {
      BlockingQueue<Integer> evens = new ArrayBlockingQueue<Integer>(1);
      BlockingQueue<Integer> odds = new ArrayBlockingQueue<Integer>(1);
      even e = new even(evens);
      odd o = new odd(odds);
      sum s = new sum(evens, odds);

      e.start();
      o.start();
      s.start();
      s.waitUntilDone();
   }
}

class sum extends Thread
{
    private final BlockingQueue<Integer> in1;
    private final BlockingQueue<Integer> in2;

    private final CountDownLatch done = new CountDownLatch(1);
    public sum(BlockingQueue<Integer> in1, BlockingQueue<Integer> in2)
    {
        this.in1 = in1;
        this.in2 = in2;
    }

    public void waitUntilDone() throws InterruptedException
    {
       done.await();
    }
    public void run()
    {
        try
        {
           while (true)
           {
              int a = in1.take();
              int b = in2.take();
              if (a == -1 && b == -1)
                 break;

              int c = a + b;
              System.out.println(a);
              System.out.println(b);
              System.out.println(c);
           }
           done.countDown();
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

class even extends Thread
{
    private final BlockingQueue<Integer> out;

    public even(BlockingQueue<Integer> out)
    {
       this.out = out;
    }
    public void run()
    {
        try
        {
            for(int i = 0; i < 10; i += 2)
               out.put(i);

            out.put(-1);
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

class odd extends Thread
{
   private final BlockingQueue<Integer> out;

   public odd(BlockingQueue<Integer> out)
   {
      this.out = out;
   }
    public void run()
    {
        try
        {
            for(int i = 1;i < 10; i += 2)
               out.put(i);

           out.put(-1);
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

典型的输出是:

0
1
1
2
3
5
4
5
9
6
7
13
8
9
17
Sums are complete
于 2012-10-06T03:42:53.360 回答
0

您需要一种将数字从生产者线程(偶数和奇数)“传递”到“消费者”线程的方法。

“最简单”但不是最好的方法是一个可变数组,只有一个条目——你必须同步/锁定某些东西(数组?)以避免并发线程破坏它。

也许更简单更好的方法可能是使用“双端队列”,例如 ArrayDeque。这使得值可以放在一端,而从另一端移除。同样,对它的访问需要同步。

创建所有线程外部的队列,然后将它们传入/或使其可见。

class Example {
    protected Deque<Integer> queueEven = new ArrayDeque<Integer>();
    protected Deque<Integer> queueOdd = new ArrayDeque<Integer>();
    // you can synchronize on some mutable flag to finish, too.

    class Even extends Thread {
        public void run() {
            for (int i = 0; i < 10; i += 2) {
                synchronized (queueEven) {
                    queueEven.add( i);
                }
            }
        } 
    } 

    class Odd extends Thread {
        public void run() {
            for (int i = 1; i < 10; i += 2) {
                synchronized (queueOdd) {
                    queueOdd.add( i);
                }
            }
        } 
    } 

    class AddEvenOdd extends Thread {
        public void run() {
             while (true) {
                 int even;
                 synchronized (queueEven) {
                     even = queueEven.removeFirst();
                 }
                 int odd;
                 synchronized (queueOdd) {
                     odd = queueOdd.removeFirst();
                 }
                 int result = even + odd;
                 System.out.println("result="+result);
             }
        }
    }
}
于 2012-10-06T03:52:59.697 回答