【java多线程】线程复制

代码来自:https://blog.csdn.net/evankaka/article/details/51627380 

 //此线程组及其子组中的所有活动线程复制到指定数组中。
    public int enumerate(ThreadGroup list[]) {
        checkAccess();
    return enumerate(list, 0, true);
    }
     //此线程组及其子组中的所有活动线程复制到指定数组中。
    public int enumerate(ThreadGroup list[], boolean recurse) {
        checkAccess();
    return enumerate(list, 0, recurse);
    }
    //此线程组中的所有活动线程复制到指定数组中。如果 recurse 标志为 true,则还包括对此线程的子组中的所有活动线程的引用。如果数组太小而无法保持所有线程,则    //忽略额外的线程。
    private int enumerate(ThreadGroup list[], int n, boolean recurse) {
    int ngroupsSnapshot = 0;
    ThreadGroup[] groupsSnapshot = null;
    synchronized (this) {
        if (destroyed) {
        return 0;
        }
        int ng = ngroups;
        if (ng > list.length - n) {//防止list放不下线程数目
        ng = list.length - n;
        }
        if (ng > 0) {
        System.arraycopy(groups, 0, list, n, ng);//复制线程组
        n += ng;
        }
        if (recurse) { //取得其子组
        ngroupsSnapshot = ngroups;
        if (groups != null) {
                    groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
        } else {
            groupsSnapshot = null;
        }
        }
    }
    if (recurse) {//复制子组
        for (int i = 0 ; i < ngroupsSnapshot ; i++) {
        n = groupsSnapshot[i].enumerate(list, n, true);
        }
    }
    return n;
    }

其实复制来说,不太难,注释写的清楚的部分就不说了,主要看看

System.arraycopy()【

native方法

一维数组:元素是基础类型,原值传给新数组:值传递、副本,修改副本不影响原值

二维数组:数组的第一维装的是一维数组的引用,第二维是元素值,使用该方法后,第一维的引用被复制给新数组的第一维(两个数组的第一维指向相同的‘那些数组’)此时改变其中任何一个数组的元素的值,其实都修改了‘那些数组’的元素的值,所以原数组和新数组的元素值都一样 

public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)       
:从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
1、src引用的源数组,dest引用的目标数组
2、srcPos:源数组起始位置,destPos模板数组起始位置,length:复制的长度
3、源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被分别复制到目标数组中的 destPos 到 destPos+length-1 位置。  

速度:

   数组小、调用次数多:不必for复制数组块

  数组比较大,有优势:使用的是内存复制、省去大量数组寻址访问的时间

Array.copyOf():【

/**
 * @Description 复制指定的数组, 如有必要用 null 截取或填充,以使副本具有指定的长度
 * 对于所有在原数组和副本中都有效的索引,这两个数组相同索引处将包含相同的值
 * 对于在副本中有效而在原数组无效的所有索引,副本将填充 null,当且仅当指定长度大于原数组的长度时,这些索引存在
 * 返回的数组属于 newType 类

 * @param original 要复制的数组
 * @param 副本的长度
 * @param 副本的类
 * 
 * @return 原数组的副本,截取或用 null 填充以获得指定的长度
 * @throws NegativeArraySizeException 如果 newLength 为负
 * @throws NullPointerException 如果 original 为 null
 * @throws ArrayStoreException 如果从 original 中复制的元素不属于存储在 newType 类数组中的运行时类型

 * @since 1.6
 */
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

数组拷贝时调用的是本地方法 System.arraycopy() 

复制指定的数组内容来扩容,对不同的基本数据类型都有对应的重载方法

返回的数组是新的数组对象,原数组对象仍是原数组对象,不变,该拷贝不会影响原来的数组

Native()

Native Method就是一个Java调用非Java代码的接口,定义时不提供实现体,实现体由非java语言在外面实现

可以和其他一些修饰符连用(无差别),但是abstract方法和Interface方法不能用native来修饰。【】native暗示这些方法有实现体,不过非java,abstract指明这些方法是没有实现体的;

可以返回如何java类型,也可以进行异常控制,可以在native method的本地实现中访问所有的java特性(依赖所访问的java特性的实现)

并不会对其他类调用这些本地方法产生任何影响,实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法;可以被继承,子类可以用java语言重写这个方法;【

适用情况:

1、为了使用底层主机平台的某个特性,而这个特性不能通过JAVA API访问。
2、为了访问一个老系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的。
3、为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。

实现步骤:

  1、在Java中声明native()方法,然后编译。
  2、用javah产生一个.h文件。
  3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件)。
  4、将第三步的.cpp文件编译成动态链接库文件。
  5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。

猜你喜欢

转载自blog.csdn.net/ma15732625261/article/details/81329350