You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何访问TimerTask内修改的类变量并实现双向同步

问题核心原因

首先纠正你的认知错误:匿名内部类访问外部类的成员变量时,持有的是外部类实例的引用,并不是复制变量副本,你遇到的不同步问题主要来自三个原因:

  • 原示例代码存在语法错误:main是静态方法,不能直接访问非静态的count、fooTimer成员和startTimerTask实例方法,你必须先实例化Foo类对象才能操作对应成员,这是你运行结果不符合预期的首要原因
  • 线程可见性问题:Timer启动的是独立后台线程,和主线程属于不同线程,没有可见性保证的前提下,线程会缓存变量值,感知不到其他线程对变量的修改
  • 线程安全问题:count的自增、赋值操作不是原子性的,多线程并发修改时会出现值覆盖的问题

你之前用单元素数组测试仍然有问题,也是因为没有处理可见性和同步逻辑导致的。

实现方案

要实现主线程和TimerTask对count的修改双向同步,推荐以下两种成熟方案:

方案1:使用AtomicInteger原子类(推荐)

java.util.concurrent.atomic.AtomicInteger自带原子操作保证和变量可见性,无需手动加锁,代码简洁性能好,修改后的可运行代码如下:

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

public class Foo {
    // 用AtomicInteger替代基础类型int,线程安全自带可见性
    private final AtomicInteger count = new AtomicInteger(0);
    private Timer fooTimer;

    public void startTimerTask() {
        TimerTask fooTimerTask = new TimerTask() {
            @Override
            public void run() {
                // 原子自增,直接操作共享的count实例
                int currentVal = count.incrementAndGet();
                System.out.println("TimerTask输出:" + currentVal);
            }
        };
        fooTimer.scheduleAtFixedRate(fooTimerTask, 0, 2000);
    }

    public static void main(String args[]) throws InterruptedException {
        // 先实例化Foo对象,所有操作基于同一个实例的成员
        Foo fooInstance = new Foo();
        fooInstance.fooTimer = new Timer();
        fooInstance.startTimerTask();

        // 延迟1秒模拟任务运行一段时间后主线程修改count
        Thread.sleep(1000);
        // 主线程修改count,修改结果会自动同步到TimerTask
        int afterModify = fooInstance.count.addAndGet(5);
        System.out.println("主线程修改后输出:" + afterModify);
    }
}

运行后你会看到主线程加5之后,TimerTask后续的自增会基于修改后的值累加,双向修改完全同步。

方案2:volatile+同步锁(基础类型实现方案)

如果你坚持要用基础int类型实现,可以通过加volatile关键字保证可见性,加同步锁保证操作原子性,核心代码片段如下:

public class Foo {
    // volatile保证变量可见性,禁止线程缓存count值
    private volatile int count = 0;
    // 全局锁对象,所有修改count的操作都要持有这把锁
    private final Object countLock = new Object();
    private Timer fooTimer;

    public void startTimerTask() {
        TimerTask fooTimerTask = new TimerTask() {
            @Override
            public void run() {
                synchronized (countLock) {
                    count++;
                    System.out.println("TimerTask输出:" + count);
                }
            }
        };
        fooTimer.scheduleAtFixedRate(fooTimerTask, 0, 2000);
    }

    public static void main(String args[]) throws InterruptedException {
        Foo fooInstance = new Foo();
        fooInstance.fooTimer = new Timer();
        fooInstance.startTimerTask();

        Thread.sleep(1000);
        // 主线程修改也要加同一把锁
        synchronized (fooInstance.countLock) {
            fooInstance.count +=5;
            System.out.println("主线程修改后输出:" + fooInstance.count);
        }
    }
}

内容的提问来源于stack exchange,提问作者Aakash Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 09:36:05