`
liuInsect
  • 浏览: 133360 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

从线程间通信看到的关于基本类型封包的问题

阅读更多
本文描述了在某种特殊场景下JDK编译器对 Java 基本类型的封包操作。
其原理非常简单,但是现象却非常 非常的迷惑人。可以让我们从另外一个角度看待jdk对基本类型的封包。
 
本文代码的原意是想找到一种当future超时后,可以尽量快的终止掉还在运行的future(事实上,future超时后(在主线程抛出超时异常后),future线程并不会停止,直到它运行结束,自然消亡。)
 
先上代码:
 
主函数:
 
package thread.InteruptTest;

import java.io.IOException;
import java.util.concurrent.*;

/**
* 通过线程池 开启一个线程去处理
* 模拟请求来时,开启一个线程处理请求的场景
* Created with IntelliJ IDEA.
* User: liukunyang
* Date: 13-12-13
* Time: 上午9:51
* To change this template use File | Settings | File Templates.
*/
public class Main {

    public static void main(String[] args) throws Exception {

        ThreadPoolExecutor exec = new ThreadPoolExecutor(0, 10,
                5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),new ThreadPoolExecutor.CallerRunsPolicy());

        TestThread tt = new TestThread();
        exec.submit( tt );

        //保持主线程存货, console端观察结果
        System.in.read();
    }

}
 
再看TestThread类:
 
package thread.InteruptTest;

import java.util.concurrent.*;

/**
* 
*
* 再启动一个线程池去提交 future 任务,该线程会在等待5秒后尝试获取future结果
* 并捕获future的超时异常。 最后设置future的 cancel 标志位,如果运行future的线程检查到标志位
* 改变就可以停止掉自己。
* Created with IntelliJ IDEA.
* User: liukunyang
* Date: 13-12-13
* Time: 上午9:55
* To change this template use File | Settings | File Templates.
*/
public class TestThread extends  Thread {

    private ThreadPoolExecutor threadPoolExecutor =
                                    new ThreadPoolExecutor(0, 10, 5, TimeUnit.SECONDS,
                                    new LinkedBlockingQueue<Runnable>(),new ThreadPoolExecutor.CallerRunsPolicy());

    ;


    @Override
    public void run() {
        ThreadLocal th = new ThreadLocal();
        DivideFuture df = new DivideFuture();

        final Future future =  threadPoolExecutor.submit(df);

        try {
            //5秒后在超时,
            //给子线程5秒的时间打印 变量isC1,isC2,isC3的值
            System.out.println( "1"+future.get(5,TimeUnit.SECONDS) );

        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (ExecutionException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (TimeoutException e) {
            System.out.println("超时拉");
        }finally {
            df.cancel();
            future.cancel(true);
        }

    }
}

 
 
DivideFuture 类:
 
package thread.InteruptTest;

import java.util.concurrent.Callable;

/**
* 使用了三种不同类型的标志位,用来更好的说明 jdk对基本类型的封包操作
* 使用threadlocal的原因是 如果call 方法再调用了其他bean 的其他方法 仍然可以通过threadlocal 获取到cancel的标志位 这里为了简单没有增加调用其他方法的代码
* 但是不影响说明原理
* Created with IntelliJ IDEA.
* User: liukunyang
* Date: 13-12-13
* Time: 上午11:05
* To change this template use File | Settings | File Templates.
*/
public class DivideFuture implements Callable {

    private ThreadLocal thISC1 = new ThreadLocal();
    private ThreadLocal<Boolean> thISC2 = new ThreadLocal<Boolean>();
    private ThreadLocal thISC3 = new ThreadLocal();

    private boolean isC1;
    private Boolean isC2;
    private RichBoolean isC3;


    /**
     * 修改isC1,isC2,isC3的标志位
     */
    public void cancel(){
        isC1 = true;
        isC2 = true;
        isC3.setValue(true);

    }

    @Override
    public Object call() throws Exception {
        //在线程调用时,再将isC初始化,
        //是的threadLocal取到的线程是执行该方法的线程
        isC1 = false;
        isC2 = false;
        isC3 = new RichBoolean(false);
        thISC1.set(isC1);
        thISC2.set(isC2);
        thISC3.set(isC3);
        // 每隔一秒获取一下标志位的值
        for(int i=0; i<10 ; i++){
            try{
                Thread.sleep(1000);
            }catch(Exception e){

            }
            System.out.println(i);
            System.out.println( "变量 isC1 的值:" + isC1 );
            System.out.println( "变量 isC1 通过ThreadLocal获取的值:" + thISC1.get() );

            System.out.println( "变量 isC2 的值:" + isC2 );
            System.out.println( "变量 isC2 通过ThreadLocal获取的值:" + thISC2.get() );

            System.out.println( "变量 isC3 的值:" + isC3 );
            System.out.println( "变量 isC3 通过ThreadLocal获取的值:" + thISC3.get() );
        }
        return "this is callable";
    }
}
 
最后是辅助bean:
 
package thread.InteruptTest;

/**
* Created with IntelliJ IDEA.
* User: liukunyang
* Date: 13-12-13
* Time: 下午2:03
* To change this template use File | Settings | File Templates.
*/
public class RichBoolean {

    private boolean value;

    public RichBoolean(boolean value) {
        this.value = value;
    }

    public void setValue(boolean value) {
        this.value = value;
    }

    public boolean isValue() {
        return value;
    }
}
 
 
猜猜打印的结果是啥?
 
注意红色和蓝色部分。
 
0
变量 isC1 的值:false
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:false
变量 isC2 通过ThreadLocal获取的值:false
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
1
变量 isC1 的值:false
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:false
变量 isC2 通过ThreadLocal获取的值:false
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
2
变量 isC1 的值:false
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:false
变量 isC2 通过ThreadLocal获取的值:false
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
3
变量 isC1 的值:false
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:false
变量 isC2 通过ThreadLocal获取的值:false
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
4
变量 isC1 的值:false
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:false
变量 isC2 通过ThreadLocal获取的值:false
超时拉
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
5
变量 isC1 的值:true
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:true
变量 isC2 通过ThreadLocal获取的值:false
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
6
变量 isC1 的值:true
变量 isC1 通过ThreadLocal获取的值:false
变量 isC2 的值:true
变量 isC2 通过ThreadLocal获取的值:false
变量 isC3 的值:thread.InteruptTest.RichBoolean@5740bb
变量 isC3 通过ThreadLocal获取的值:thread.InteruptTest.RichBoolean@5740bb
 
 
想想为什么isC1,isC2中,future自身的变量变为了true 而他们对应的threadlocal中的值却还是false???????
难道是线程之间不能使用这种方式访问同一个变量?
那为什么isC3又是和我们想想的一样的?
 
其实仔细推导后发现原理非常简单
 
看看DivideFuture.class

内层的红色框中说明,我们cancel时是将isC2的变量重新赋值了,也就是说isC2指向了一个新的对象 而thISC2 里面还是老的值,所以他们打印出来的结果不同。
 
同理,isC1 = true 这句话因为jdk 封包操作的原因类似isC2也是重新new了一个对象,isC1指向了新对象,而thISC1中还是老对象。所以导致了上述的结果。
 
也算是对jdk封包,解包操作的一个新理解吧。
 

 
  • 大小: 29.7 KB
0
1
分享到:
评论

相关推荐

    封包对比工具_封包对比工具_封包_天龙封包_

    在IT行业中,封包对比工具是一种非常实用的软件开发与网络分析工具,它主要用于比较两个或多个数据包的差异,帮助开发者或者网络安全专家理解网络通信中的变化和问题。标题"封包对比工具_封包对比工具_封包_天龙封包...

    封包全套工具_发封包工具_发送封包工具_封包工具_封包全套工具_封包拦截

    封包工具能够让我们看到这些封包的内容,帮助我们理解网络通信的过程。 2. **发送封包**: 这个功能允许用户模拟网络通信,向指定的IP地址或端口发送特定的数据包。这对于测试网络服务、诊断连接问题或者开发网络...

    飞雪封包个人版封包分析

    4. **故障排查(Troubleshooting)**:在遇到网络问题时,飞雪封包工具可以提供详细的通信记录,帮助定位问题原因,比如查看是否有丢包、延迟过高等现象。 5. **安全监控(Security Monitoring)**:通过分析数据包...

    封包助手 封包助手 封包助手

    在IT行业中,"封包助手"通常指的是一个用于软件打包和发布的工具,它可以帮助开发者将应用程序的各种组件整合在一起,形成一个可分发的安装包。封包助手简化了软件部署的过程,使得用户能够轻松地下载、安装和更新...

    易语言封包截收教程

    通过截收和分析这些封包,开发者可以了解程序在网络层的实际操作,排查网络问题,优化通信效率,甚至进行安全检测。 在易语言中实现封包截收,首先需要了解和利用相关的API函数或者库。例如,Windows平台下的...

    抓封包C++原程序.zip_c++封包_socket抓包程序_封包_抓包_抓封包

    在IT领域,网络通信是至关重要的部分,而封包抓取技术则是理解网络通信过程、调试网络应用或分析网络数据的关键工具。C++作为一种强大的编程语言,被广泛用于开发网络应用,包括网络封包的抓取和解析。本文将深入...

    封包工具下载封包工具封包工具

    封包工具封包工具封包工具封包工具封包工具封包工封包工具具封包工具

    VC 封包拦截源代码

    封包拦截可能涉及隐私和法律问题,因此在实际应用中,必须确保遵循相关法规,并获取必要的授权。 以上就是VC环境下封包拦截的基本概念和源代码实现的关键点。在实际项目中,开发者需要根据具体需求进行调整和优化...

    ab封包对比工具

    封包,或者网络数据包,是网络通信中的基本单元,包含了发送者和接收者的信息,以及传输的数据。当两个或多个封包进行对比时,我们可以分析它们的差异,这有助于找出网络问题、安全漏洞,或者在游戏中检测作弊行为。...

    易语言自创封包协议模块源码

    在IT行业中,网络通信是至关重要的一个领域,而封包协议则是网络通信的基础。...这不仅有助于提升你的编程技能,也有助于你理解和解决实际网络通信问题。如果你对网络编程有兴趣,这个资源无疑是一个很好的学习起点。

    封包全套工具,封包工具下载,Java

    在IT行业中,"封包工具"通常指的是网络封包分析工具,它们可以帮助开发者和网络管理员深入理解网络通信过程,捕获、查看、分析网络数据包。这类工具在故障排查、性能优化、安全检测等方面有着广泛的应用。Java作为一...

    网页游戏封包发送源码

    封包,全称为数据包,是网络通信中的基本传输单位。在网络游戏中,玩家的操作如移动、攻击等都会被转化为特定的数据包,由客户端发送到服务器进行处理。封包发送技术就是通过模拟或篡改这些数据包,以达到改变游戏...

    封包助手.rar软件,封包截取

    封包助手是一款专门用于网络封包截取的软件工具,其主要功能是帮助用户捕获、分析和理解网络上的数据传输。在IT行业中,封包截取是网络诊断、安全审计和性能优化的重要手段。这款名为"封包助手"的软件包含以下几个...

    封包调试器 (打印和监视网络封包的工具)

    封包调试器是一个封包打印和查看工具,您可以使用它来打印发送和接收的网络封包。例如:可以用来监视网络游戏中客户端与服务器通讯的数据封包,您只需通过Hook Socket的方式截获网络封包后通过封包调试器打印出来...

    封包拦截器MiniSniffer 1.0

    通过捕获网络传输的数据包,我们可以查看网络通信的细节,包括源和目标地址、端口号、协议类型以及数据包的内容。这对于网络安全测试、性能优化和问题诊断至关重要。 二、MiniSniffer 1.0的特点与优势 1. 直接操作...

    封包抓包工具

    封包抓包工具是网络分析和调试的重要辅助软件,它能捕获网络中的数据包,以便于分析网络通信过程中的信息流动。在这个压缩包中,包含了一款迷你封包抓包器以及WPE吾爱专用版,它们是两种不同的工具,各自具有独特的...

    关于API HOOK拦截封包原理

    封包拦截是网络通信中的一种技术,它涉及到读取、分析甚至修改在网络上传输的数据包。API Hook与封包拦截的结合,特别是在网络安全和数据分析领域,可以提供强大的功能。例如,我们可以通过Hook网络相关的API,如...

    封包讲解

    封包是网络通信的基本单元,不同的协议定义了不同类型的封包格式。 ### 封包讲解中的关键技术点 #### 1. 封包结构 封包结构决定了如何解析和处理接收到的数据。典型的封包结构包括: - **头部**:包含了关于封包的...

    关于封包操作的实例修改发送拦截WSPSEND,SEND几种不同的模式

    在IT行业中,封包操作是网络通信中一个关键的概念,特别是在网络编程、协议分析和网络安全领域。本实例主要探讨的是如何通过修改发送拦截WSPSEND和SEND来实现不同模式的封包操作。这些操作通常涉及到对网络数据传输...

Global site tag (gtag.js) - Google Analytics