如何让java中的线程读取两个独立线程的值

如何让java中的线程读取两个独立线程的值,java,multithreading,Java,Multithreading,嗯。我需要做三个线程:一个获取奇数,一个获取偶数,一个将奇数和偶数相加。输出应该是这样的(1,2,3,3,4,7…)。 我是线程新手,对线程的工作方式仍不确定,但到目前为止,我已经做到了: class even extends Thread { public void even() { Thread ThreadEven = new Thread(this); start(); } public void run()

嗯。我需要做三个线程:一个获取奇数,一个获取偶数,一个将奇数和偶数相加。输出应该是这样的(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();

    } 
} 
类甚至扩展了线程
{
公共空间
{
螺纹偶数=新螺纹(此);
start();
} 
公开募捐
{
尝试
{
对于(int i=0;i<10;i+=2)
{
系统输出打印LN(i);
}
睡眠(1000);
}
捕获(例外e)
{
System.out.println(“错误:线程中断”);
} 
} 
}
类奇数扩展线程
{ 
公共空间(奇数)
{
螺纹奇数=新螺纹(此);
start();
} 
公开募捐
{
尝试
{
对于(int i=1;i<10;i+=2)
系统输出打印LN(i);
睡眠(1000);
}
捕获(例外e)
{
System.out.println(“错误:线程中断”);
} 
} 
}
奇数类
{
公共静态void main(字符串参数[])
{
偶数e=新偶数();
奇数o=新的奇数();
} 
} 
这会打印出0,2,4…然后是1,3,5。 如何交织?交错是我想要的吗?我应该同步线程吗? 我不明白的是如何将奇数和偶数线程的值放入第三个线程中,以相加和。
如果代码的格式不正确,请提前道歉。

如前所述,这是一个高级问题,是的,在尝试此操作之前,您应该阅读大量教程。即使对于这个简短的程序,如果我没有花很多时间仔细研究的话,我也不可能写出来。(提示-买这本书,都在里面。)

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

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");
        }
    }
}
您需要一种将数字从生产者线程(偶数和奇数)传递到“消费者”线程的方法

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

也许更简单、更好的方法是使用“双端队列”,如ArrayQueue。这样可以将值放在一端,然后从另一端删除。同样,对它的访问需要同步

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

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);
             }
        }
    }
}
类示例{
受保护的Deque queue偶数=新的ArrayDeque();
protected Deque queueOdd=new ArrayDeque();
//您也可以在某个可变标志上进行同步以完成。
类甚至扩展了线程{
公开募捐{
对于(int i=0;i<10;i+=2){
已同步(排队偶数){
加入(i);
}
}
} 
} 
类奇数扩展线程{
公开募捐{
对于(int i=1;i<10;i+=2){
已同步(奇数){
加入(i);
}
}
} 
} 
类AddEventOdd扩展线程{
公开募捐{
while(true){
整数偶数;
已同步(排队偶数){
偶数=Queue偶数。removeFirst();
}
int奇数;
已同步(奇数){
奇数=queueOdd.removeFirst();
}
int结果=偶数+奇数;
System.out.println(“结果=”+结果);
}
}
}
}

请花些时间重新格式化代码。现在很难读懂。请参阅:另外,在对象构造函数中,您不应该泄漏
this
。这就建立了即时的比赛条件。请参阅:“如果我没有获得代码的正确格式,请事先道歉。”-说真的,如果你知道格式不好,在你点击“发布问题”按钮之前修复此问题会更尊重读者。它仍然是一团混乱。将所有“制表符”字符替换为空格。在这两个类中,您都在构造一个新的
线程
,然后立即将其丢弃。然后从构造函数调用
start()
。你的类是一个
线程
;你把它延长了。你不应该那样调用
start()
。在进一步讨论之前,我真的建议您阅读关于线程(可能还有基本java)的Oracle教程。谢谢。很好的解释。真的,真的很感激。我也要去拿那本书。我也是一个纯C/C++背景的人,很难理解Java。特别是线程。我喜欢这些“生产者”和“消费者”的术语。当我试图学习线程时,这更有意义。通过这两个示例,我可以看到线程的深度。看来这些排队是必要的
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);
             }
        }
    }
}