我需要同步这个吗?如果是这样,怎么办?

时间:2014-05-07 17:03:21

标签: java multithreading synchronization

我有一个简单的服务器任务,需要监听数据包并经常保存它们。这是我正在使用的代码:

class ServerTask implements Runnable {

    private final Socket client;
    private final Timer timer;
    private Packet lastPacket;

    public ServerTask(Socket client) {
        this.client = client;
        this.timer = new Timer();

        timer.scheduleAtFixedRate(
            new TimerTask() {
                @Override
                public void run() {
                    saveLastPacketToLog();
                }
            }, 60*1000, 60*1000);
    }

    public void run() {
        try (ObjectInputStream fromClient = new ObjectImputStream(client.getOutputStream())) {
            while (running) {
                lastPacket = (Packet) fromClient.readObject();
            }
        } catch (Exception e) {
            ... 
        }
    }

    public void saveLastPacketToLog() {
        // ... open file, serialize lastPacket and write it there
    }
}

现在,由于Timer使用另一个Thread,我可能应该同步lastPacket的访问权限。我必须这样做吗?如果是这样,怎么办?我虽然做了这个,但我不确定,因为我对多线程没有多少经验:

class ServerTask implements Runnable {

    private final Socket client;
    private final Timer timer;
    private Packet lastPacket;

    public ServerTask(Socket client) {
        this.client = client;
        this.timer = new Timer();

        timer.scheduleAtFixedRate(
            new TimerTask() {
                @Override
                public void run() {
                    saveLastPacketToLog();
                }
            }, 60*1000, 60*1000);
    }

    public void run() {
        try (ObjectInputStream fromClient = new ObjectImputStream(client.getOutputStream())) {
            while (running) {
                synchronized(this){
                    lastPacket = (Packet) fromClient.readObject();
                }

            }
        } catch (Exception e) {
            ... 
        }
    }

    public synchronized void saveLastPacketToLog() {
        // ... open file, serialize lastPacket and write it there
    }
}

2 个答案:

答案 0 :(得分:3)

  

我是否必须[同步对lastPacket]的访问权限?

不,您不必这样做:因为您有兴趣在计时器触发时大致写出最后一个数据包,并且因为接收器线程不会改变现有数据包,所以不需要同步。

使lastPacket volatile变得足以实现逻辑:

private volatile Packet lastPacket;

注意:上面假设fromClient.readObject();返回一个全新的对象,该对象独立于lastPacket对象。

答案 1 :(得分:0)

在每个请求到来时使用池中的新线程或线程,