2009-08-12 49 views
3

我有两个线程从控制器类运行。第一个线程收到SMS消息,只要程序处于启动状态,应该继续运行。另一个线程用于计算单位的GPS位置。如何同步(d)方法并修改父对象内的对象属性?

控制器启动SMS线程并等待文本消息。如果文本消息符合某些标准,GPS位置线程将启动并且坐标被发送回控制器。

对于每个线程中,我使用的格式如下:

reader = new Reader(this); 
     new Thread(reader).start(); 

读取器类,然后使用控制器的参考,以便它可以调用在控制器中的方法,包括:

public void ReceivedCommand(String address) { 
    [..] 
} 

然后,该方法创建一个GPS线程实例,它自己调用父对象(线程?)调用的方法ReceivedLocation,然后设置新的SMS消息(TextMessage对象)。问题是,SMS线程只能返回原始发件人地址(回复),我需要使用GPS线程,以便我可以为SMS消息设置Payload。所以现在我有两种方法使用相同的对象(TextMessage对象),但我想确保第一种方法(SMS地址设置器)不改变地址,而GPS线程获取GPSLocation设置。

可以同步块内ReceivedCommand()

  • 的地址添加到TextMessage对象,
  • 运行GPS螺纹
  • 让GPS线程调用第二个方法(ReceivedLocation()
  • 而让该方法改变TextMessage对象?
+0

我已经编辑约50我的答案:在这种情况下,只要你synchronize在实地访问明确,一切都会好起来 - 例如,您可能需要更新有条件地对另一个人的价值一个字段现在的时间 - 可能值得再读一次。请注意,同步你的'TextMessage'对象的方法并不总是足够的 - 可能有你想要控制的* atomic *操作(即'compareAndSet') – 2009-08-12 07:47:00

回答

4

首先,创建线程非常昂贵。你可能会更好使用线程池(如可在java.util.concurrent包(一个ExecutorService上找到)以及养殖关闭您的作品与

共享对象上使用​​将确保没有两个线程可以。里面一个​​块同时但是,如果我创建和​​块内启动一个线程,I(即第一个线程)可能已经退出块之前第二个线程实际开始:

final TextMessage msg = //... 
Thread t = new Thread(r); 
synchronized (msg) { 
    t.start(); 
} //the other thread is still running and now this thread has not synchronized on the msg 

那么你的处理器R:

Runnable r = new Runnable() { 
    public void run() { 
     synchronized (msg) { //only any use if readers are alse sync-ed 
      msg.setGpsLocation(findGpsLocation(msg)); 
     } 
    } 
} 

只要TextMessage对象是线程安全(即字段访问是​​)你应该没问题,并且没有必要明确地以这种方式同步

注意​​在语义上重要的不只是从线程调度的角度来看,也从一个事实,即it affects data visibility between threads(例如,不同步,就无法确保在一个线程中进行的修改将是可见的到另一个)。

修改我的回答对使用ExecutorService

final TextMessage msg = //... 
ExecutorService worker = Executors.newSingleThreadedExecutor(); 
Future<?> f = worker.submit(r); //the future represents the work 

这里,r会是什么样子:

Runnable r = new Runnable() { 
    public void run() { 
     GpsLocation loc = findGpsLocation(msg); 
     msg.setGpsLocation(loc); //the setter is synchronized 
    } 
} 

这是setGpsLocation方法应该是​​(与getter和沿两个线程所需的任何其他字段访问)。请注意,如果您需要字段间的原子性,那么仅同步字段访问并不总是足够的。

synchronized (msg) { 
    if (msg.getGpsLocation().isIn(AMERICA)) 
     msg.append(" DUDE!") 
}