【问题标题】:How to pass information to a thread once it has been created创建线程后如何将信息传递给线程
【发布时间】:2013-01-12 17:38:27
【问题描述】:

如果您查看代码,我有两个 ArrayList,它们被调用、按下和释放,它们是全局的。我要做的是用要按下的键更新这些数组,然后将这些更新的数组传递给我的线程,或者更新线程..这是我对我必须做的事情有点迷失的部分.

当前示例(如​​果运行未测试)是我在实际程序中的基本示例。当我运行它时,它会按一次按钮,然后它会抛出错误,我不记得错误,因为我现在无法测试它,但这与我使用线程的方式有关。

问题 线程启动后,如何将数组传递给我的线程。

代码示例:

import oscP5.OscEventListener;
import oscP5.OscMessage;
import oscP5.OscP5;
import oscP5.OscStatus;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Main implements OscEventListener {

protected BlockingQueue<Integer> _KeyQue = new ArrayBlockingQueue<>(1024);

Producer producer = new Producer(this._KeyQue);
Consumer consumer = new Consumer(this._KeyQue);
ThreadTest threadTest = new ThreadTest(this._KeyQue);

Thread prod;
Thread con;
Thread threadT;

OscP5 osc = new OscP5(this, 22556);

public static void main(String[] argv) {
    Main main = new Main();
    main.setup();
}

public void setup() {
    prod = new Thread(producer);
    con = new Thread(consumer);
    threadT = new Thread(threadTest);

    prod.start();
    con.start();
    threadT.start();

}

@Override
public void oscEvent(OscMessage theMessage) {
    float val = Float.parseFloat(theMessage.arguments()[0].toString());

    if (val == 1.0) {
        producer.addKey(KeyEvent.VK_W);
        producer.addKey(KeyEvent.VK_S);
    } else {
        consumer.removeKey(KeyEvent.VK_S);
    }
   threadTest.run();
}

@Override
public void oscStatus(OscStatus theStatus) {}

public class Producer implements Runnable {
    protected BlockingQueue<Integer> _KeyQue = null;

    public void addKey(int key) {
        try {
            this._KeyQue.put(key);
            System.out.println("Key " + key +" added to queue");
        } catch (InterruptedException e) {
            System.out.println(e.getMessage());
        }
    }

    public Producer(BlockingQueue<Integer> _KeyQue) {
        this._KeyQue = _KeyQue;
    }

    public void run() {

    }
}

public class Consumer implements Runnable {
    protected BlockingQueue<Integer> _KeyQue = null;

    public void removeKey(int key) {
        try {
            this._KeyQue.remove(key);
            System.out.println("key " + key + " removed from queue");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    public Consumer(BlockingQueue<Integer> _KeyQue) {
        this._KeyQue = _KeyQue;
    }

    public void run() {

    }
}

public class ThreadTest implements Runnable {

    protected BlockingQueue<Integer> _KeyQue = null;

    public ThreadTest(BlockingQueue<Integer> _KeyQue) {
        this._KeyQue = _KeyQue;
    }

    public void run() {
        try {
            Robot robot = new Robot();

            while(!this._KeyQue.isEmpty()) {
                for (Integer x : this._KeyQue) {
                    System.out.println("Keys in que: " + x);
                    Thread.sleep(500);
                }
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
}

编辑: 好的,所以我看了一下线程和 BlockingQueue 的,但我仍然想不通的是如何继续运行 ThreadTest 的 run() 方法不锁定程序。在此示例中,它根本不运行。当我直接调用 threadTest.run() 时,它会将程序锁定在其中,并且不允许添加或删除元素。

所以我需要做的是能够在后台运行一个不断运行的线程,循环通过 *_KeysQueue()* 并且在这个例子中,打印出与键。这一切都应该发生,同时允许我添加和删除密钥。

【问题讨论】:

  • 如果您不确定我要做什么,请提出一些探索性问题。很难说清楚我想要做什么。
  • 我认为您需要确定错误是什么...
  • 另外,不清楚您的实际问题是什么。
  • 我知道我没有正确使用线程。所以我只能假设如果我学会了如何使用线程并能够用它更新信息,它将解决问题。
  • 如果你不能测试,你怎么知道问题是否解决了?

标签: java multithreading arraylist


【解决方案1】:

您可以拥有一个BlockingQueue 和一个方法来添加将从其他线程调用的元素。你可以有一个静态方法addKey,可以从其他线程访问它,它会寻找将新密钥添加到BlockingQueue

您可以在那里使用the producer-consumer pattern,您可以在博客The Java Specialists 中看到这本书Java Concurrency In Practice 或将我引向这本书的链接。这本书有所有队列、并发或同步列表的示例、实现代码来做几件事的方法,所有这些都不需要停下来阅读 50 页的内容。每个问题的示例和几段。

【讨论】:

    【解决方案2】:

    在你的类中有一个 setter 方法

    public class ThreadTest implements Runnable {
        ....
        public void setPressedList(ArrayList<Integer> e) {
           this.pressed = e;
        }
        public void setReleasedList(ArrayList<Integer> f)
        {
           this.released = f
        }
    }
    

    【讨论】:

    • 好的,这可能会有所帮助,但我仍然有一个问题,这是一个已实例化的线程。没有我必须处理的变量。正如您在顶部所说的那样;线程 t = 新线程(新线程测试(bla,bla))。那么如何访问这些方法呢?
    • 只使用 t.setPressedList(list) ;
    【解决方案3】:

    ArrayList 不是线程安全的,所以你不应该这样使用它们:它可以工作也可以失败。

    此外,您应该使用某种同步机制,而不是忙于等待,这会消耗资源。

    所以看看 BlockingQueue 集合,它将为您提供一个简单的线程之间的数据传递机制。

    【讨论】:

    • 我去看看。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 2011-06-01
    相关资源
    最近更新 更多