• Java中的多线程操作初探


    问题引出:

    说是java,其实还是在做android的时候遇到的问题,在android 4.0以后,访问网络必须在新线程中实现,所以才会遇到这个问题。只是为了方面说明问题,才新建一个java项目。在main函数里,用自定义的类创建新对象时,新对象的值是怎么变化的。首先看一下项目的目录

    项目中包括两个文件,一个是first.java这个是main函数所在的位置,second.java是自定义类。

    step1、

    second.java代码

    public class second {
        int a;
        int b;
        
        public second()
        {
            set();
        }
        private void set() {
            // TODO Auto-generated method stub
            a = 1;
            b = 2;
            
            
        }
    }

    first.java代码

    public class first 
    {
    	public static void main(String args[])
    	{
    		second se = new second();
    		System.out.println(se.a+"&&"+se.b);
    		
    	}
    }
    

    显而易见,输出结果是a=1,b=2;这没什么争议。

    step2、现在,我们在second.java,再自定义一个内部类,就叫test吧。代码如下:

    public class second {
    	int a;
    	int b;
    	class test
    	{
    		int ta;
    		int tb;
    	}
    	test mtest[];
    	public second()
    	{
    		set();
    	}
    	private void set() {
    		// TODO Auto-generated method stub
    		a = 1;
    		b = 2;
    		
    		mtest = new test[2];
    		mtest[0] = new test();
    		mtest[1] = new test();
    		mtest[0].ta=3;
    		mtest[0].tb=4;
    		mtest[1].ta=5;
    		mtest[1].tb=6;
    	}
    }
    

    first.java代码

    public class first 
    {
    	public static void main(String args[])
    	{
    		second se = new second();
    		System.out.println(se.a+"&&"+se.b);
    		System.out.println(se.mtest[1].ta+"&&"+se.mtest[1].tb);
    	}
    }
    

    这个结果也很好得出,se.mtest[1].ta = 5,se.mtest[1].tb=6;也没问题。

    下面重点来了,上面两步都没有涉及到多线程,现在我们修改一下second.java代码,如下:

    public class second {
    	int a;
    	int b;
    	class test
    	{
    		int ta;
    		int tb;
    	}
    	test mtest[];
    	public second()
    	{
    		set();
    	}
    	private void set() {
    		// TODO Auto-generated method stub
    		a = 1;
    		b = 2;
    		
    		new Thread(new Runnable() {		
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				mtest = new test[2];
    				mtest[0] = new test();
    				mtest[1] = new test();
    				mtest[0].ta=3;
    				mtest[0].tb=4;
    				mtest[1].ta=5;
    				mtest[1].tb=6;
    			}
    		}).start();
    	}
    }
    

    first.java代码不变

    public class first 
    {
    	public static void main(String args[])
    	{
    		second se = new second();
    		System.out.println(se.a+"&&"+se.b);
    		System.out.println(se.mtest[1].ta+"&&"+se.mtest[1].tb);
    	}
    }
    

    这次结果应该是什么呢?如果你说结果不变,那就打错特错了。

    口说无凭,结果截图如下:

      

    对,你没有看错,我也没有传错照片,就是抛出异常。那么问题来了,这是为什么呢?

    如果要搞清这个问题,就要先清楚电脑的多线程的处理机制。

    在计算机组成原理中,我们知道,电脑的多线程并不是真正的平行关系,严格意义上讲,只有一个线程。

    举个例子来说,第一个想到的就是绣花(和双面绣差不多),在绣制的时候我们只看一面,但是绣完之后两面都完成了。其实和这个原理一样。

    首先,我们只有一根线,用这一根线绣出两面。在正面绣一针之后,穿到反面再绣一针,就这样依次循环。

    电脑的多线程处理也是如此,假设有两个线程A,B,A执行一会,B再执行一会。当然,电脑的线程处理并不是这么简单,

    如果要再细说的话,电脑会给每个线程指定优先级,优先级决定了线程的执行顺序和分配给它的电脑资源。

    总之,严格的说多线程并不是平行关系,而是根据某种规则轮流执行,只是这中间的时间单位很短,用户基本无法察觉。

    所以,代码抛出异常的原因是:当主线程执行到最后的时候,我们新开的线程却没有执行完。以至于抛出空指针。

    怎么解决呢?那就主线程休息一会等待新线程执行结束,调用sleep函数即可。

    所以,修改后的java代码如下:

    public class first 
    {
    	public static void main(String args[])
    	{
    		second se = new second();
    		System.out.println(se.a+"&&"+se.b);
    		try {
    			Thread.sleep(5*1000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		System.out.println(se.mtest[1].ta+"&&"+se.mtest[1].tb);
    	}
    }
    

    我们让主线程休息5s。下面是执行结果:

    结果就是这样。

    附:

    1、代码有问题不要找我,是他自己长歪的

    2、欢迎批评之

    3、转载就注明出处by不剃头的一休哥

  • 相关阅读:
    计算机硬件介绍
    SC-控制Windows服务的命令
    SQL Server 2008中的Service SID 介绍
    内置系统账户:Local system/Network service/Local Service 区别
    用于sql server启动的账户
    sql server常见服务
    oracle和sql server的区别(1)
    架构设计学习(一)
    web项目分层设计
    封装继承多态
  • 原文地址:https://www.cnblogs.com/hearzeus/p/4111303.html
Copyright © 2020-2023  润新知