android.os.Process.myTid与Thread.currentThread.getId的区别

关键总结

1、android.os.Process.myTid返回的是操作系统级别的线程实例的线程号,在JNI开发过程我们一般称之为natvie线程的线程号
2、Thread.currentThread.getId返回的是JVM级别的线程实例对应的线程号(一个递增的Id),JVM线别的线程称之为Java线程
3、一个native线程当前只能绑定一个Java线程,但可以多次绑定线程实例,这个绑定线程实例过程其实是发生在我们的创建的native线程将要跟Java代码做交互时前的的attchJVM的操作,如果每次都交互前后都做attach与deattch的操作,会导致natvie线程不断的绑定到JVM线程是不同的。这种情况你在回调的Java代码中调用android.os.Process.myTid与Thread.currentThread.getId的返回值就会是不一样的了

代码示例

      // 这个方法多个native线程会调用到,
        public void log(int level, final String msg) {
            int tid = android.os.Process.myTid();
            Thread thread = Thread.currentThread();
            long tid2 = thread.getId();

            Log.i("test", String.format("android.os.Process.myTid = %d, getId = %d, thread = " +
                            "%s, thread hashCode = %d", tid, tid2,
                    thread.toString(), thread.hashCode()));
        }

在这里插入图片描述

如上图所示,26128是Natvie线程的线程号,会频繁的回调Java的方法,然后JNI的交互策略是—每次都调AttachCurrentThread方法,然后调用Java的方法后就DetachCurrentThread。所以你会看到它每次绑定的线程都是新的,从线程号可以看出来

Java ThreadLocal

在如上case的情况下,如果native回调到Java方法中就不能再用ThreadLocal实例的get方法了,因为每次都是一个新的Java线程,每次都会new一份ThreadLocal容器中的实例,就背离了使用ThreadLocal的初衷!ThreadLocal缓存线程的线程数据的Key是Java的线程实例(可以看下Threadlocal的get方法的源码),C++ std中也有ThreadLocal,那才真实跟系统线程相关的线程存储数据

示例代码如下

   private static final String                  DATE_FORMAT = "HH:mm:ss.SSS";
        private static       ThreadLocal<DateFormat> threadLocal = new ThreadLocal<>();

        private static DateFormat getDateFormat() {
            DateFormat df = threadLocal.get();
            if (df == null) {
                df = new SimpleDateFormat(DATE_FORMAT);
                Log.i("test", "new SimpleDateFormat");
                threadLocal.set(df);

            }
            return df;
        }

        private static String formatDate(Date date) {
            String result = "";
            try {
                result = getDateFormat().format(date);

            } catch (Exception e) {

            }
            return result;
        }

        public void log(int level, final String msg) {
            int tid = android.os.Process.myTid();
            Thread thread = Thread.currentThread();
            long tid2 = thread.getId();
            Log.i("test", String.format("android.os.Process.myTid = %d, getId = %d, thread = " +
                            "%s, thread hashCode = %d", tid, tid2,
                    thread.toString(), thread.hashCode()));
            formatDate(new Date());
        }

在这里插入图片描述

关键代码

myTid

    /**
     * See <a href="http://man7.org/linux/man-pages/man2/gettid.2.html">gettid(2)</a>.
     */
    public static int gettid() { return Libcore.os.gettid(); }

ThreadLocal.get

    /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值