Как сохранить значение переменной потока в многопоточной программе - PullRequest
0 голосов
/ 16 мая 2018

У меня есть код, который порождает новый поток каждые 5 секунд, и каждый поток периодически выводит значение счетчика. Всего запускается до 10 потоков.

Вот код:

public static void main(String[] args) {
    ScheduledExecutorService task = Executors.newScheduledThreadPool(10);
    AtomicInteger counter = new AtomicInteger(0);
    int i = 0;
    while (i < 10) {
        // sleep 5 seconds
        sleep(5);
        task.scheduleAtFixedRate(() -> {
            String threadName = Thread.currentThread().getName();
            int newCounter = counter.get();
            System.out.println(String.format("[%s] counter = %d" , threadName, newCounter));
        }, 0, 2, TimeUnit.SECONDS);

        counter.getAndIncrement();
        ++i;
    }
}

private static void sleep(int sleepTime) {
    try {
        TimeUnit.SECONDS.sleep(sleepTime);
    } catch (InterruptedException ie) {

    }
}

Вот вывод:

[pool-1-thread-1] counter = 1
[pool-1-thread-1] counter = 1
[pool-1-thread-2] counter = 1
[pool-1-thread-3] counter = 1
[pool-1-thread-1] counter = 2
[pool-1-thread-2] counter = 2
[pool-1-thread-4] counter = 2
[pool-1-thread-5] counter = 2
[pool-1-thread-3] counter = 2
[pool-1-thread-1] counter = 3
[pool-1-thread-7] counter = 3
[pool-1-thread-6] counter = 3
[pool-1-thread-8] counter = 3
[pool-1-thread-4] counter = 3
[pool-1-thread-9] counter = 3
[pool-1-thread-5] counter = 3
[pool-1-thread-10] counter = 3
[pool-1-thread-1] counter = 4
   .......

Я хочу, чтобы каждый поток выводил свое первоначальное значение, например, pool-1-thread-1 должен выводить 0 или 1 (в зависимости от того, увеличивается ли счетчик первым или поток запускается первым) все время, второй поток должен постоянно выдавать предыдущий счетчик + 1, ... такой как:

[pool-1-thread-1] counter = 1
[pool-1-thread-1] counter = 1
[pool-1-thread-2] counter = 2
[pool-1-thread-3] counter = 3
[pool-1-thread-1] counter = 1
[pool-1-thread-2] counter = 2
[pool-1-thread-4] counter = 4
[pool-1-thread-5] counter = 5
[pool-1-thread-3] counter = 3
[pool-1-thread-1] counter = 1
[pool-1-thread-7] counter = 7
  .......

Мой вопрос заключается в том, как заставить локальную переменную newCounter сохранять свое первоначальное значение в каждом потоке. Я могу думать о том, чтобы сохранить сопоставление имени потока с его исходным значением в хэш-таблице, безопасной для потока. Есть ли более чистый способ сделать это? Спасибо

1 Ответ

0 голосов
/ 16 мая 2018

Чтобы привязать значение к определенному потоку, вы можете использовать переменную ThreadLocal . Образец класса ThreadId в javadoc может быть легко адаптирован для решения вашего варианта использования.

public static void main(String[] args) {
    ScheduledExecutorService task = Executors.newScheduledThreadPool(10);
    AtomicInteger counter = new AtomicInteger(0);
    ThreadLocal<Integer> id = ThreadLocal.withInitial(counter::incrementAndGet);
    int i = 0;
    while (i < 10) {
        // sleep 5 seconds
        sleep(5);
        task.scheduleAtFixedRate(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println(String.format("[%s] counter = %d" , threadName, id.get()));
        }, 0, 2, TimeUnit.SECONDS);

        ++i;
    }
}

private static void sleep(int sleepTime) {
    try {
        TimeUnit.SECONDS.sleep(sleepTime);
    } catch (InterruptedException ie) {

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...