实例变量与局部变量的区别

在日常开发中,我们会创建实例变量和局部变量来处理我们的需求。在非多线程环境中我们发现它们的区别不太大,无非就是作用域不同而已。但在多线程环境中可能会发生我们意想不到的结果。请看下面的事例。

局部变量在多线程环境中的测试

/**
 * 用户登录
 *
 * @author Sama
 * @author admin@jilinwula.com
 * @date 2017-03-15 10:35
 * @since 1.0.0
 */
public class Userinfo {
    public void login(String username) {
        try {
            int role = 0;
            if ("admin".equals(username)) {
                role = 1;
                System.out.println("管理用户登录");
                Thread.sleep(1000);
            } else {
                role = 2;
                System.out.println("普通用户登录");
            }
            System.out.println(String.format("uername: %s	role: %s", username, role));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 管理用户请求
 *
 * @author Sama
 * @author admin@jilinwula.com
 * @date 2017-03-15 10:44
 * @since 1.0.0
 */
public class RequestAdmin extends Thread {

    private Userinfo userinfo;

    public RequestAdmin(Userinfo userinfo) {
        this.userinfo = userinfo;
    }

    @Override
    public void run() {
        userinfo.login("admin");
    }
}
/**
 * 普通用户请求
 *
 * @author Sama
 * @author admin@jilinwula.com
 * @date 2017-03-15 10:44
 * @since 1.0.0
 */
public class RequestUser extends Thread {

    private Userinfo userinfo;

    public RequestUser(Userinfo userinfo) {
        this.userinfo = userinfo;
    }

    @Override
    public void run() {
        userinfo.login("user");
    }
}
/**
 * 测试类
 *
 * @author Sama
 * @author admin@jilinwula.com
 * @date 2017-03-15 10:49
 * @since 1.0.0
 */
public class RequestRun {
    public static void main(String[] args) {
        Userinfo userinfo = new Userinfo();
        RequestAdmin admin = new RequestAdmin(userinfo);
        RequestUser user = new RequestUser(userinfo);
        admin.start();
        user.start();
    }
}
管理用户登录
普通用户登录
uername: user	role: 2
uername: admin	role: 1

我们看到输出是交替进行的,说明这两个线程是异步执行的,虽然我们没有在方法中添加synchronized关键字,但它们还是线程安全的。也就是说在多线程环境中局部变量都是线程安全的。

实例变量在多线程环境中的测试

/**
 * 用户登录
 *
 * @author Sama
 * @author admin@jilinwula.com
 * @date 2017-03-15 10:35
 * @since 1.0.0
 */
public class Userinfo {

    private int role = 0;

    public void login(String username) {
        try {
            if ("admin".equals(username)) {
                role = 1;
                System.out.println("管理用户登录");
                Thread.sleep(1000);
            } else {
                role = 2;
                System.out.println("普通用户登录");
            }
            System.out.println(String.format("uername: %s	role: %s", username, role));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
管理用户登录
普通用户登录
uername: user	role: 2
uername: admin	role: 2

我们看到实例变量在多线程中就可能会出现线程安全问题了。原因我们已经在其它篇里面说过,解决的办法就是在方法上添加synchronized关键字。

/**
 * 用户登录
 *
 * @author Sama
 * @author admin@jilinwula.com
 * @date 2017-03-15 10:35
 * @since 1.0.0
 */
public class Userinfo {

    private int role = 0;

    public synchronized void login(String username) {
        try {
            if ("admin".equals(username)) {
                role = 1;
                System.out.println("管理用户登录");
                Thread.sleep(1000);
            } else {
                role = 2;
                System.out.println("普通用户登录");
            }
            System.out.println(String.format("uername: %s	role: %s", username, role));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
普通用户登录
uername: user	role: 2
管理用户登录
uername: admin	role: 1
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论