有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在父对象中同步(d)方法和修改对象的属性?

我有两个从控制器类运行的线程。第一个线程接收SMS消息,只要程序处于started状态,它就应该继续运行。另一个线程用于计算单位GPS位置

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

对于每个线程,我使用了以下格式:

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

然后,reader类使用控制器的引用,以便调用控制器中的方法:

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

然后,该方法创建一个GPS线程实例,该实例本身从父对象(线程?)调用一个方法调用ReceivedLocation,然后设置新的SMS消息(TextMessage对象)。问题是SMS线程只能返回原始发件人的地址(回复),我需要使用GPS线程,以便设置SMS消息的有效负载

现在我有两个方法使用同一个对象(TextMessage对象),但我想确保第一个方法(SMS地址设置器)在GPS线程设置GPSLocation时不会更改地址

可以在ReceivedCommand()内同步块:

  • 将地址添加到TextMessage对象
  • 运行GPS线程
  • 让GPS线程调用第二个方法(ReceivedLocation()
  • 让这个方法改变TextMessage对象

共 (1) 个答案

  1. # 1 楼答案

    首先,线程创建是昂贵的。您最好使用线程池(可以在java.util.concurrent包(an ExecutorService)中找到),并将您的工作分配给它

    在共享对象上使用synchronized将确保在a synchronized内不能同时有两个线程。但是,如果我在synchronized块中创建并启动一个线程,我(即第一个线程)可能在第二个线程实际启动之前退出了该块:

    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对象是线程安全的(即字段访问是synchronized),就应该可以了,不需要以这种方式显式同步

    Note that synchronized is semantically important not just from the perspective of thread-scheduling but also from the fact that it affects data visibility between threads (for example, without synchronization, you cannot be sure that modifications made in one thread will be visible to another).

    修改我的答案以使用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方法,应该是synchronized(以及两个线程所需的getter和任何其他字段访问)。请注意,如果需要跨字段的原子性,仅同步字段访问并不总是足够的。例如,您可能希望根据另一个字段的值有条件地更新一个字段——在这种情况下,只要在字段访问期间显式地synchronize,一切都可以:

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