• 多线程访问成员变量与局部变量


    package com.wc82;
    
    public class ThreadClassVarTest
    {
        public static void main(String[] args)
        {
            HelloThread r = new HelloThread();
    
            Thread t1 = new Thread(r);
            Thread t2 = new Thread(r);
    
            t1.start();
            t2.start();
    
        }
    
    }
    
    class HelloThread implements Runnable
    {
        private int i=0;
    
        @Override
        public void run()
        {
    
           for(;i<50;) {
    			synchronized (this) {
    				System.out.println("Hello number: " + i++);
    			}
    			
    			try {
    				Thread.sleep(20);
    				//Thread.sleep((long) Math.random() * 1000);  这样的写法是错误的,因为括号的优先级,
    				//相当于Thread.sleep(0),这时线程不再进行阻塞,各个线程之间会抢占cpu,接口会出错,会打印出50
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    
        }
    }
    

      

    该例子中,HelloThread类实现了Runnable接口,其中run()方法的主要工作是输出"Hello number: "字符串加数字i,并且同时递增i,当i到达50时,退出循环。

      main()方法中生成了一个HelloThread类的对象r,并且利用这个一个对象生成了两个线程。

      程序的执行结果是:顺次打印了0到49的数字,共50个数字。

      这是因为,i是成员变量,则HelloThread的对象r只包含这一个i,两个Thread对象因为由r构造,所以共享了同一个i。

      当我们改变代码时(原先的成员变量i被注释掉,增加了方法中的局部变量i):

    将以下代码修改

    for(;i<50;) 
    

      改为

     for(int i=0;i<50;)
    

      

    如注释中所述,由于局部变量对于每一个线程来说都有自己的拷贝,所以各个线程之间不再共享同一个变量,输出结果为100个数字,实际上是两组,每组都是0到49的50个数字,并且两组数字之间随意地穿插在一起。 

    得到的结论如下:

      如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,它们对该成员变量是彼此影响的,也就是说一个线程对成员变量的改变会影响到另一个线程。

      如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝(即便是同一个对象中的方法的局部变量,也会对每一个线程有一个拷贝),一个线程对该局部变量的改变不会影响到其他线程。

  • 相关阅读:
    自定义滚动条样式
    git相关操作
    mac添加hosts记录的步骤
    vue 中input框的blur事件和enter事件同时使用时,触发enter事件时blur事件也会被触发的方法解决
    VUE 子窗口如何调用父窗口的方法-- PC端项目
    小程序自定义tabbar的tabbar切换之后图标会闪烁情况处理
    微信小程序自定义tabbar
    js 数组和类数组的区别
    vue中私有样式(scoped)中修改其他组件的样式
    放大镜特效
  • 原文地址:https://www.cnblogs.com/toSeeMyDream/p/6369451.html
Copyright © 2020-2023  润新知