Solving shared variables when ThreadLocal threads are concurrent

1, ThreadLocal: "water can carry a boat and also cover it" is the most appropriate way to describe it.

1.1 his original intention is to solve the problem of variable sharing when threads are concurrent. However, due to over design, such as weak reference and hash collision, it is difficult to understand and expensive to use. Instead, it becomes a high failure point, which is easy to cause memory leakage, dirty data, and object update.

1.2 start with the example code of cs live game, and analyze the ThreadLocal source code in detail.

  • At the beginning of the game, everyone has a gun [number of bullets, number of enemies killed, number of lives]
  • Set the ThreadLocal object as a shared variable to solve the problem of data inaccuracy caused by concurrent modification. Set the initial value uniformly. Each thread is independent of each other in modifying this value
  • Everyone is a thread
package com.wang.thread;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author wyn-365
 * @date 2020/5/6 10:59
 */
public class CsGameByThreadLocal {
    private static final Integer BULLET_NUMBER = 1500;
    private static final Integer KILLED_ENEMIES = 0;
    private static final Integer LIFE_VALUE = 10;
    private static final Integer TOTAL_PLAYERS = 10 ;

    // Random numbers to show different data for each object
    private static final ThreadLocalRandom RANDOM
            = ThreadLocalRandom.current();

    // Number of initialization bullets
    private static final ThreadLocal<Integer> BULLET_NUMBER_THREADLOCAL
            = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return BULLET_NUMBER;
        }
    };

    // Initialize the number of enemies killed
    private static final ThreadLocal<Integer> KILLED_ENEMIES_THREADLOCAL
            = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return KILLED_ENEMIES;
        }
    };

    // Initialization life
    private static final ThreadLocal<Integer> LIFE_VALUE_THREADLOCAL
            = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return LIFE_VALUE;
        }
    };

    // Define each team member
    private static class Player extends Thread {
        @Override
        public void run() {
            Integer bullets = BULLET_NUMBER_THREADLOCAL.get() - RANDOM.nextInt(BULLET_NUMBER);
            Integer killEnemies = KILLED_ENEMIES_THREADLOCAL.get() + RANDOM.nextInt(TOTAL_PLAYERS / 2);
            Integer lifeValue = LIFE_VALUE_THREADLOCAL.get() - RANDOM.nextInt(LIFE_VALUE);

            System.out.println(getName()+",BULLET_NUMBER is " + bullets);
            System.out.println(getName()+",KILLED_ENEMIES is " + killEnemies);
            System.out.println(getName()+",LIFE_VALUE is " + lifeValue);

            BULLET_NUMBER_THREADLOCAL.remove();
            KILLED_ENEMIES_THREADLOCAL.remove();
            LIFE_VALUE_THREADLOCAL.remove();
        }
    }


    /**
     * Main method everyone is a thread
     */
    public static void main(String[] args) {
        for (int i = 0; i < TOTAL_PLAYERS; i++) {
            new Player().start();
        }
    }
}

Tags: Programming Java

Posted on Wed, 06 May 2020 07:14:28 -0700 by genericnumber1