Java 每次线程执行其运行时获取值/返回某些内容
我有两个线程在运行。一个是Java 每次线程执行其运行时获取值/返回某些内容,java,multithreading,return,frame,runnable,Java,Multithreading,Return,Frame,Runnable,我有两个线程在运行。一个是TimeStepThread,另一个是CarThread。 CarThread每500毫秒运行一次。TimeStepThread以我给定的任何间隔运行。现在,每500毫秒,CarThread就会更新道路上汽车位置的移动。然而,每次调用TimeStepThread时,我都想得到汽车位置值。例如,我有一辆车,不管怎样,每500毫秒更新一次,但每2秒我想用该车的位置设置一个标签 我的课程设置如下: public class TimeStepThread extends Thr
TimeStepThread
,另一个是CarThread
。
CarThread
每500毫秒运行一次。TimeStepThread
以我给定的任何间隔运行。现在,每500毫秒,CarThread
就会更新道路上汽车位置的移动。然而,每次调用TimeStepThread
时,我都想得到汽车位置值。例如,我有一辆车,不管怎样,每500毫秒更新一次,但每2秒我想用该车的位置设置一个标签
我的课程设置如下:
public class TimeStepThread extends Thread {
private final Car car;
private final JFrame frame;
public TimeStepThread(Car car, JFrame frame) {
this.car = car;
this.frame = frame;
}
@Override
public void run() {
while(true) {
Thread.sleep(2000);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame.setTitle(Integer.toString(car.getPosition()));
}
}
}
}
}
模拟
类具有TimeStepThread
和CarThread
模拟中
(或者更确切地说是在帧中),我希望在每个时间步间隔更新汽车位置的值。因此,每2000ms,我需要在模拟类中更新/返回一些内容
只是我不知道怎么做。由于我的线程位于模拟
中,因此我无法从运行()调用模拟
方法,更不用说它会有点混乱。也许是听众
编辑:我已经可以在timestep线程中访问汽车了。这不是问题。我正在使用一个容器类来保存这些汽车,两个线程都可以访问,CarThread
也会更新它。我的问题是仿真类在每次调用TimeStepThread时都有一个更新的字符串,或者在每次调用TimeStepThread时都有一个更新的帧标签。您可以在仿真类中放置一个ConcurrentLinkedQueue
-Car
线程向队列发送位置更新。然后,Timestep
线程处理所有位置更新(poll
队列,直到它返回空)并放置标签
或者,您可以将阻塞队列
放入模拟
类中,并让一个线程从队列中持续获取
,并更新位置信息
通过这种方式,您可以根据需要添加更多的车辆,而无需更改模拟
代码-所有车辆都会将更新发送到同一队列。我认为最好的方法是为您提供一个车辆进度监听器。你可以这样做
public interface CarProgressListener {
void positionChanged(Position currentPosition);
}
...
Position initialPosition = // get it from somewhere.
CarThread car = new CarThread(initialPosition);
TimestepThread timestepThread = new TimestepThread(initialPosition);
car.addListener(timestepThread);
...
然后让您的TimestepThread
实现这个接口,并在CarThread
注册它
public CarThread extends Thread {
private final Collection<CarProgressListener> progressListeners = new LinkedList<>();
// other stuff
public void addListener(CarProgressListener listener) {
this.progressListeners.add(listener);
}
}
public TimestepThread extends Thread implements CarProgressListener {
private Position lastHeardCarPosition;
// remenber to initiate this thread with the first car position.
@Override
public void positionChanged(Position currentPosition) {
this.lastHeardCarPosition = currentPosition;
}
}
两个线程中的两个类都需要访问汽车列表
在本例中,汽车是汽车类的实例
时间步线程有一个实现其工作的类。(正在读取车辆的位置。)
car线程有一个实现其工作的类。(正在更新位置。)
每个执行类型类将访问car对象,以使用位置更改信息更新它们,或读取任何内容。例如,您必须同步car类(或下面提到的car容器)中访问该位置的实例方法,这样各个线程就不会相互重叠
这里有两种类似的实现方法
1) 每次创建汽车时,都会将其传递给两个工作类中的每一个。他们每个人都有自己的所有汽车的内部清单。如果你扔掉一辆车,你必须告诉他们两个
2) 开始时,为两个工作类中的每一个提供一个对汽车容器类的引用。也许只是一个列表,一个并发列表。也许是自定义类。当您创建一辆汽车时,您告诉汽车容器类(通过添加它)。当你丢了一辆车,你也会告诉它
至于模拟类,您希望在汽车位置发生变化时通知它。同样有两种方法,但它们是相似的
在这两种情况下,都必须将仿真类实例传递给正在进行更新的类。simulation类有一个方法,比如说updateCar()
,更新类在完成更新后调用该方法
1) 版本1-对simulation类实例的调用只告诉它发生了变化。simulation类中的代码将识别发生了什么变化并进行处理,或者只是更新所有内容
2) 版本2-对simulation类实例的调用将包括已更改的所有汽车的列表。simulation类不必搜索以查找更改的内容
而且它只能更新不断变化的事物
棘手的部分是,您必须记住,对更新方法的调用发生在更新线程中。因此,例如,如果您使用Swing更新屏幕上的文本,则必须使用SwingWorker来获取事件线程中发生的更新
如果无法将该工作转移到安全线程,则必须确保所有正确的事情都是并发的或同步的,这样它们就不会相互影响。我认为您不需要列表或任何其他数据结构。可以这么简单:
public class Car
private volatile int position;
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}
public class CarThread extends Thread {
private final Car car;
public CarThread(Car car) {
this.car = car;
}
@Override
public void run() {
Thread.sleep(500);
car.setPosition(//whatever)
}
}
public class TimeStepThread extends Thread {
private final Car car;
public CarThread(Car car) {
this.car = car;
}
@Override
public void run() {
Thread.sleep(2000);
int position = car.getPosition()
// do stuff
}
}
确保你把同一辆车传给所有人,你会没事的
这个答案还假设您不需要排队等待所有位置的更改,只有最近的位置才有意义,如果您使用它在地图或类似的东西上绘制汽车的位置,这是合理的
编辑
要将所有这些放在一起,请尝试以下方法:
public class TimeStepThread extends Thread {
private final Car car;
private final JFrame frame;
public TimeStepThread(Car car, JFrame frame) {
this.car = car;
this.frame = frame;
}
@Override
public void run() {
while(true) {
Thread.sleep(2000);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame.setTitle(Integer.toString(car.getPosition()));
}
}
}
}
}
我的线程已经可以访问汽车对象。我的线程已经可以访问汽车对象了。把问题的措辞改了一点。对不起,那么我不明白这个问题。只要从TimeStepThread每隔2000ms调用getPosition(),您就会看到从CarThread计算的最新值。我不需要线程中的值,我需要帧jLabel中的值,每2000ms更新一次。