`
Donald_Draper
  • 浏览: 951672 次
社区版块
存档分类
最新评论

WindowsSelectorImpl解析一(FdMap,PollArrayWrapper)

    博客分类:
  • NIO
阅读更多
Channel接口定义:http://donald-draper.iteye.com/blog/2369111
AbstractInterruptibleChannel接口定义:http://donald-draper.iteye.com/blog/2369238
SelectableChannel接口定义:http://donald-draper.iteye.com/blog/2369317
SelectionKey定义:http://donald-draper.iteye.com/blog/2369499
SelectorProvider定义:http://donald-draper.iteye.com/blog/2369615
AbstractSelectableChannel定义:http://donald-draper.iteye.com/blog/2369742
NetworkChannel接口定义:http://donald-draper.iteye.com/blog/2369773
ServerSocketChannel定义:http://donald-draper.iteye.com/blog/2369836
Selector定义:http://donald-draper.iteye.com/blog/2370015
AbstractSelector定义:http://donald-draper.iteye.com/blog/2370138
SelectorImpl分析 :http://donald-draper.iteye.com/blog/2370519
引言:
在上一篇文章中,我们看了SelectorImpl的相关key集合和方法,先来回顾一下:
     SelectorImpl有4个集合分别为就绪key集合,key集合,key集合的代理publicKeys及就绪key集合的代理publicSelectedKeys;实际是两个集合就绪key集合和key集合,publicSelectedKeys和publicKeys是其他线程访问上述两个集合的代理。
     SelectorImpl构造的时候,初始化选择器提供者SelectorProvider,创建就绪key集合和key集合,然后初始化就绪key和key集合的代理,初始化过程为,如果nio包的JDK版本存在bug问题,则就绪key和key集合的代理集合直接引用就绪key和key集合。否则将当前key集合包装成不可修改的代理集合publicKes,将就绪key集合包装成容量固定的集合publicSelectedKeys。
其他线程获取选择器的就绪key和key集合,实际上返回的是key集合的代理publicKeys和就绪key集合的代理publicSelectedKeys。
     select方法的3中操作形式,实际上委托给为lockAndDoSelect方法,方法实际上是同步的,可安全访问,获取key集合代理publicKeys和就绪key代理集合publicSelectedKeys,然后交给doSelect(long l)方法,这个方法为抽象方法,待子类扩展。实际的关闭选择器操作implCloseSelector方法,首先唤醒等待选择操作的线程,唤醒方法wakeup待实现,同步选择器,就绪key和key集合的代理publicKeys,publicSelectedKeys,调用implClose完成实际的关闭通道工作,待子类实现。
     可选通道注册方法,首先注册的通道必须是AbstractSelectableChannel类型,并且是SelChImpl实例。更具可选择通道和选择器构造选择key,设置选择key的附加物,同步key集合代理,调用implRegister方法完成实际的注册工作,implRegister方法待子类实现。
     processDeregisterQueue方法,主要是遍历取消key集合,反注册取消key,实际的反注册工作由implDereg方法,implDereg方法待子类扩展。成功,则从集合中移除。
今天我们来看的选择器的具体实现WindowsSelectorProvider,在这篇文章中,我们要关注的是这几个方法,选择操作中的doSelect(long l),注册key操作的implRegister方法,处理取消key集合方法中implDereg方法和唤醒方法wakeup。
我们先从打开选择器开始
//Selector
  public static Selector open() throws IOException {
        return SelectorProvider.provider().openSelector();
    }

//SelectorProvider
  
 public static SelectorProvider provider() {  
            synchronized (lock) {  
                if (provider != null)  
                    return provider;  
           //在与当前线程相同访问控制权限的环境中,加载SelectorProvider实例  
                return AccessController.doPrivileged(  
                    new PrivilegedAction<SelectorProvider>() {  
                        public SelectorProvider run() {  
                                if (loadProviderFromProperty())  
                        //获取系统配置的SelectorProvider  
                                    return provider;  
                                if (loadProviderAsService())  
                         //获取类加载路径下的SelectorProvider  
                                    return provider;  
                        //加载默认的SelectorProvider  
                                provider = sun.nio.ch.DefaultSelectorProvider.create();  
                                return provider;  
                            }  
                        });  
            }  
    }  

来看默认的DefaultSelectorProvider
//DefaultSelectorProvider
 
  package sun.nio.ch;  
      
    import java.nio.channels.spi.SelectorProvider;  
      
    // Referenced classes of package sun.nio.ch:  
    //            WindowsSelectorProvider  
      
    public class DefaultSelectorProvider  
    {  
        private DefaultSelectorProvider()  
        {  
        }  
        public static SelectorProvider create()  
        {  
            //默认的WindowsSelectorProvider  
            return new WindowsSelectorProvider();  
        }  
    }  

从上面了可以看出选择器的默认实现为WindowsSelectorImpl,下面我们来具体看一下,先看一下变量的定义,具体每个变量及集合含义我们现在可能不完全解释清楚,一般从字面上可以看出它的意思,对于不能完全理解的变量,我们在后面的文章中,再纠正。
final class WindowsSelectorImpl extends SelectorImpl
{
    private final int INIT_CAP = 8;//选择key集合,key包装集合初始化容量
    private static final int MAX_SELECTABLE_FDS = 1024;//最大选择key数量
    private SelectionKeyImpl channelArray[];//选择器关联通道集合
    private PollArrayWrapper pollWrapper;//存放所有文件描述对象(选择key,唤醒管道的源与sink通道)的集合
    private int totalChannels;//注册到选择的通道数量
    private int threadsCount;//选择线程数
    private final List threads = new ArrayList();//选择操作线程集合
    private final Pipe wakeupPipe = Pipe.open();//唤醒等待选择操操的管道
    private final int wakeupSourceFd;//唤醒管道源通道文件描述
    private final int wakeupSinkFd;//唤醒管道sink通道文件描述
    private Object closeLock;//选择器关闭同步锁
    private final FdMap fdMap = new FdMap();//存放选择key文件描述与选择key映射关系的Map
    private final SubSelector subSelector = new SubSelector();//子选择器
    private long timeout;//超时时间,具体什么意思,现在还没明白,在后面在看
    private final Object interruptLock = new Object();//中断同步锁,在唤醒选择操作线程时,用于同步
    private volatile boolean interruptTriggered;//是否唤醒等待选择操的线程
    private final StartLock startLock = new StartLock();//选择操作开始锁
    private final FinishLock finishLock = new FinishLock();//选择操作结束锁
    private long updateCount;//更新数量,具体什么意思,现在还没明白,在后面在看
    static final boolean $assertionsDisabled = !sun/nio/ch/WindowsSelectorImpl.desiredAssertionStatus();
    static 
    {
        //加载nio,net资源库
        Util.load();
    } 
}

//Util
static void load()
    {
label0:
        {
            synchronized(sun/nio/ch/Util)
            {
                if(!loaded)
                    break label0;
            }
            return;
        }
        loaded = true;
	//在与当前线程相同访问控制权限的情况下,加载net和nio资源库
        AccessController.doPrivileged(new LoadLibraryAction("net"));
        AccessController.doPrivileged(new LoadLibraryAction("nio"));
        IOUtil.initIDs();
        local;
        JVM INSTR monitorexit ;
          goto _L1
        exception;
        throw exception;
_L1:
    }


//这个我们先放在这里,我们慢慢解开选择的构造
 WindowsSelectorImpl(SelectorProvider selectorprovider)
        throws IOException
    {
        super(selectorprovider);
        channelArray = new SelectionKeyImpl[8];
        totalChannels = 1;
        threadsCount = 0;
        closeLock = new Object();
        interruptTriggered = false;
        updateCount = 0L;
        pollWrapper = new PollArrayWrapper(8);
        wakeupSourceFd = ((SelChImpl)wakeupPipe.source()).getFDVal();
        SinkChannelImpl sinkchannelimpl = (SinkChannelImpl)wakeupPipe.sink();
        sinkchannelimpl.sc.socket().setTcpNoDelay(true);
        wakeupSinkFd = sinkchannelimpl.getFDVal();
        pollWrapper.addWakeupSocket(wakeupSourceFd, 0);
    }

为了更好的理解fdMap和pollWrapper作用我们来看一下这两个集合的定义:
先看FdMap
//key与key描述符映射关系Map
 private static final class FdMap extends HashMap
    {
        static final long serialVersionUID = 0L;
        private FdMap()
        {
        }
	//根据key文件描述id获取key
        private MapEntry get(int i)
        {
            return (MapEntry)get(new Integer(i));
        }
	//添加key
        private MapEntry put(SelectionKeyImpl selectionkeyimpl)
        {
            return (MapEntry)put(new Integer(selectionkeyimpl.channel.getFDVal()), new MapEntry(selectionkeyimpl));
        }
	//移除选择key
        private MapEntry remove(SelectionKeyImpl selectionkeyimpl)
        {
            Integer integer = new Integer(selectionkeyimpl.channel.getFDVal());
            MapEntry mapentry = (MapEntry)get(integer);
            if(mapentry != null && mapentry.ski.channel == selectionkeyimpl.channel)
                return (MapEntry)remove(integer);
            else
                return null;
        }
    }
    

//MapEntry
 
  private static final class MapEntry
    {
        SelectionKeyImpl ski;//选择key
	//这两个计数器,现在还不知道干什么用的,后备碰到再说
        long updateCount;//操作事件更新计数器
        long clearedCount;操作事件清除计数器
        MapEntry(SelectionKeyImpl selectionkeyimpl)
        {
            updateCount = 0L;
            clearedCount = 0L;
            ski = selectionkeyimpl;
        }
    }

从上面可以看出FdMap主要是存储选择key的,FdMap实际上是一个HashMap,key为选择key的文件描述id,value为MapEntry,MapEntry为选择key的包装Entry,里面含有更新计数器updateCount和清除计数器clearedCount。

再看PollArrayWrapper,
PollArrayWrapper,我们可以这么理解为本地内存空间管理器主要是
将文件描述(选择key,唤醒管道的source和sink通道)信息及相关的兴趣操作事件存储在本地内存空间中。PollArrayWrapper是通过AllocatedNativeObject来操作底层存储空间
//PollArrayWrapper
class PollArrayWrapper
{
    private AllocatedNativeObject pollArray;//底层内存空间
    long pollArrayAddress;//内存空间起始位置
    private static final short FD_OFFSET = 0;文件描述id开始位置
    private static final short EVENT_OFFSET = 4;//兴趣事件开始位置
    static short SIZE_POLLFD = 8;//文件描述id的长度int(4)+操作事件长度4
    //这些事件当前不能明白意思,只是简单的猜测,理解的网友给我留言,谢谢
    static final short POLLIN = 1;//添加事件
    static final short POLLOUT = 4;//拉取事件
    static final short POLLERR = 8;//操作错误
    static final short POLLHUP = 16;//操作挂起
    static final short POLLNVAL = 32;
    static final short POLLREMOVE = 2048;//移除
    static final short POLLCONN = 2;//
    private int size;
    //创建i容量的文件描述管理器
    PollArrayWrapper(int i)
    {
        int j = i * SIZE_POLLFD;
	//分配内存空间
        pollArray = new AllocatedNativeObject(j, true);
	//初始化空间起始地址
        pollArrayAddress = pollArray.address();
        size = i;//初始化容量
    }
}

//已分配的本地空间
class AllocatedNativeObject extends NativeObject
{
    AllocatedNativeObject(int i, boolean flag)
    {
        super(i, flag);
    }
    //释放本地对象空间
    synchronized void free()
    {
        //如果已分配的地址不为0,则释放空间
        if(allocationAddress != 0L)
        {
            unsafe.freeMemory(allocationAddress);
            allocationAddress = 0L;
        }
    }
}


//NativeObject,本地内存管理对象
package sun.nio.ch;
import java.nio.ByteOrder;
import sun.misc.Unsafe;

class NativeObject
{
    protected static final Unsafe unsafe = Unsafe.getUnsafe();
    protected long allocationAddress;//已分配的地址空间
    private final long address;//空间起始位置
    private static ByteOrder byteOrder = null;
    private static int pageSize = -1;//内存分页大小
    static final boolean $assertionsDisabled = !sun/nio/ch/NativeObject.desiredAssertionStatus();
    NativeObject(long l)
    {
        allocationAddress = l;
        address = l;
    }
    NativeObject(long l, long l1)
    {
        allocationAddress = l;
        address = l + l1;
    }
    //分配i大小的内存空间,flag为是否分配内存页
    protected NativeObject(int i, boolean flag)
    {
        if(!flag)
        {
            allocationAddress = unsafe.allocateMemory(i);
            address = allocationAddress;
        } else
        {
            int j = pageSize();
            long l = unsafe.allocateMemory(i + j);
            allocationAddress = l;//已分配内存空间
            address = (l + (long)j) - (l & (long)(j - 1));//空间起始位置
        }
    }
    //获取内存分页大小
    static int pageSize()
    {
        if(pageSize == -1)
            pageSize = unsafe.pageSize();
        return pageSize;
    }
}

//再来看PollArrayWrapper的其他方法
//添加选择key到文件描述包装集合i索引上
void addEntry(int i, SelectionKeyImpl selectionkeyimpl)
{
   //委托给putDescriptor
    putDescriptor(i, selectionkeyimpl.channel.getFDVal());
}

//将文件描述id-j放在索引i上
void putDescriptor(int i, int j)
{
    //委托给pollArray
    pollArray.putInt(SIZE_POLLFD * i + 0, j);
}

//NativeObject
//将文件描述id-j,放在地址i上
final void putInt(int i, int j)
{
    unsafe.putInt((long)i + address, j);
}

存放索引i文件描述信息的兴趣操作事件
 void putEventOps(int i, int j)
    {
        //委托给pollArray
        pollArray.putShort(SIZE_POLLFD * i + 4, (short)j);
    }

//NativeObject
//存放文件描述的兴趣操作事件,放在地址i上
   final void putShort(int i, short word0)
    {
        unsafe.putShort((long)i + address, word0);
    }

//获取索引i的文件描述id
int getDescriptor(int i)
{
    return pollArray.getInt(SIZE_POLLFD * i + 0);
}

//NativeObject
    final short getShort(int i)
    {
        return unsafe.getShort((long)i + address);
    }


//获取索引i的文件描述id关注的兴趣操作事件
int getEventOps(int i)
{
    return pollArray.getShort(SIZE_POLLFD * i + 4);
}

//NativeObject
    final short getShort(int i)
    {
        return unsafe.getShort((long)i + address);
    }


从上面可以好像看出一点门道,PollArrayWrapper作用即存放选择key和选择key关注的
事件,用选择key的文件描述id,表示选择key,文件描述id为int,所以占4个字节,选择key
的兴趣操作事件也为int,即4个字节,所以SIZE_POLLFD为8,文件描述id开始位置FD_OFFSET为0,兴趣事件开始位置EVENT_OFFSET为4;FD_OFFSET和EVENT_OFFSET都是相对于SIZE_POLLFD的。


再来看其他操作
//PollArrayWrapper,替换j索引上的文件描述信息为i索引对应的文件描述信息
void replaceEntry(PollArrayWrapper pollarraywrapper, int i, PollArrayWrapper pollarraywrapper1, int j)
{
    pollarraywrapper1.putDescriptor(j, pollarraywrapper.getDescriptor(i));
    pollarraywrapper1.putEventOps(j, pollarraywrapper.getEventOps(i));
}

添加唤醒管道的source通道文件描述符
void addWakeupSocket(int i, int j)
{
    putDescriptor(j, i);
    //等待唤醒描述符关注的事件是添加事件POLLIN
    putEventOps(j, 1);
}

我猜测一下这个意思,PollArrayWrapper同时存储唤醒等待选择操作的选择器的通道和唤醒通道关注事件即通道注册选择器事件,即添加选择key事件。当有通道注册到选择器,则唤醒通道,唤醒等待选择操作的选择器。
//PollArrayWrapper
//释放内存空间
void free()
{
    pollArray.free();
}

//AllocatedNativeObject
synchronized void free()
{
    if(allocationAddress != 0L)
    {
        unsafe.freeMemory(allocationAddress);
        allocationAddress = 0L;
    }
}

//PollArrayWrapper
//增加i个存储文件描述及相应的兴趣操作事件内存块
void grow(int i)
{
    //重新创建文件描述集合
    PollArrayWrapper pollarraywrapper = new PollArrayWrapper(i);
    //将原始文件描述及相关兴趣操作事件,移到新的集合中
    for(int j = 0; j < size; j++)
        replaceEntry(this, j, pollarraywrapper, j);
    //释放旧集合的空间
    pollArray.free();
    //更新pollArray,容量及起始地址
    pollArray = pollarraywrapper.pollArray;
    size = pollarraywrapper.size;
    pollArrayAddress = pollArray.address();
}

看完这两个集合,再来看WindowsSelectorImpl的构造
WindowsSelectorImpl(SelectorProvider selectorprovider)
        throws IOException
    {
        super(selectorprovider);
	//创建选择器关联通道数组,实际存的为选择key
        channelArray = new SelectionKeyImpl[8];
        totalChannels = 1;
        threadsCount = 0;
        closeLock = new Object();//关闭锁
        interruptTriggered = false;
        updateCount = 0L;
        pollWrapper = new PollArrayWrapper(8);
        wakeupSourceFd = ((SelChImpl)wakeupPipe.source()).getFDVal();//唤醒管道源通道文件描述id
        SinkChannelImpl sinkchannelimpl = (SinkChannelImpl)wakeupPipe.sink();//唤醒管道sink通道
        sinkchannelimpl.sc.socket().setTcpNoDelay(true);//设置唤醒管道sink通道的Socket为无延时
        wakeupSinkFd = sinkchannelimpl.getFDVal();
	//将唤醒管道的源通道文件描述id添加pollWrapper的索引0位置上
        pollWrapper.addWakeupSocket(wakeupSourceFd, 0);
    }

WindowsSelectorImpl默认加载net和nio资源库;WindowsSelectorImpl内锁4个,分别为关闭锁closeLock,中断锁interruptLock,startLock,finishLock后面两个的作用,目前还不清楚,后面再说;一个唤醒管道,作用尚不明确;一个注册到选择器的通道计数器totalChannels;updateCount计数器作用,尚不明确;通道集合channelArray,存放的元素实际为通道关联的选择key;pollWrapper用于存储选择key和相应的兴趣事件,及唤醒管道的源通道,唤醒管道的源通道存放在pollWrapper的索引0位置上。

关于唤醒管道的作用,现在还不是太清楚,在后面的文章中在具体讲解其作用。
我们要关注的几个方法为
1.注册key操作的implRegister方法
2.处理取消key集合方法中implDereg方法
3.选择操作中的doSelect(long l)
4.唤醒方法wakeup
5.实际关闭选择通道方法implClose
由于篇幅问题,这几个方法,放在下一篇文章中再讲

总结:
      WindowsSelectorImpl默认加载net和nio资源库;WindowsSelectorImpl内锁4个,分别为关闭锁closeLock,中断锁interruptLock,startLock,finishLock后面两个的作用,目前还不清楚,后面再说;一个唤醒管道,作用尚不明确;一个注册到选择器的通道计数器totalChannels;updateCount计数器作用,尚不明确;通道集合channelArray,存放的元素实际为通道关联的选择key;pollWrapper用于存储选择key和相应的兴趣事件,及唤醒管道的源通道,唤醒管道的源通道存放在pollWrapper的索引0位置上。
     FdMap主要是存储选择key的,FdMap实际上是一个HashMap,key为选择key的文件描述id,value为MapEntry,MapEntry为选择key的包装Entry,里面含有更新计数器updateCount和清除计数器clearedCount。
     PollArrayWrapper存放选择key和通道及其相关的操作事件。PollArrayWrapper通过AllocatedNativeObject来存储先关的文件描述及其兴趣事件,AllocatedNativeObject
为已分配的底层内存空间,AllocatedNativeObject的内存主要NativeObject来分配,NativeObject实际是通过Unsafe来分配内存。PollArrayWrapper作用即存放选择key和选择key关注的事件,用选择key的文件描述id,表示选择key,文件描述id为int,所以占4个字节,选择key的兴趣操作事件也为int,即4个字节,所以SIZE_POLLFD为8,文件描述id开始位置FD_OFFSET为0,兴趣事件开始位置EVENT_OFFSET为4;FD_OFFSET和EVENT_OFFSET都是相对于SIZE_POLLFD的。PollArrayWrapper同时存储唤醒等待选择操作的选择器的通道和唤醒通道关注事件即通道注册选择器事件,即添加选择key事件。当有通道注册到选择器,则唤醒通道,唤醒等待选择操作的选择器。

WindowsSelectorImpl解析二(选择操作,通道注册,通道反注册,选择器关闭等):
http://donald-draper.iteye.com/blog/2370862
1
1
分享到:
评论
1 楼 ezlhq 2018-07-27  
关于 PollArrayWrapper 状态含义猜测:

参考 SocketChannelImpl#translateAndSetInterestOps:
(http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/db6e25fee0f7/src/share/classes/sun/nio/ch/SocketChannelImpl.java)
 public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
        int newOps = 0;
        if ((ops & SelectionKey.OP_READ) != 0)
            newOps |= PollArrayWrapper.POLLIN;
        if ((ops & SelectionKey.OP_WRITE) != 0)
            newOps |= PollArrayWrapper.POLLOUT;
        if ((ops & SelectionKey.OP_CONNECT) != 0)
            newOps |= PollArrayWrapper.POLLCONN;
        sk.selector.putEventOps(sk, newOps);
    }

可以看出来,POLLIN是read事件,POLLOUT是write事件,POLLCONN是connection事件

参考 ServerSocketChannelImpl#translateAndSetInterestOps:
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/1a3de3cdc684/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
        int newOps = 0;

        // Translate ops
        if ((ops & SelectionKey.OP_ACCEPT) != 0)
            newOps |= PollArrayWrapper.POLLIN;
        // Place ops into pollfd array
        sk.selector.putEventOps(sk, newOps);
    }


可以看出来 POLLIN是ACCEPT事件。


其他事件还没看到

相关推荐

    Java-NIO-Netty框架学习

    资源名称:Java-NIO-Netty框架学习资源目录:【】Netty5.0架构剖析和源码解读【】Netty5用户指南【】Netty_in_Action(第五版-目录修正版)【】Netty_in_Action_v08_MEAP【】Netty_in_Action_v10_MEAP【】Netty_代码...

    基于 Java 实现的宠物医院在线挂号系统

    基于 Java 实现的宠物医院在线挂号系统 基于 Java 实现的宠物医院在线挂号系统

    天津欢乐谷官方网站html5响应式触屏版手机wap旅游网站模板.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

    基于matlab实现的混沌扰动算法来解决pso算法早熟问题,并用二者结合来训练灰色预测模型参数.rar

    基于matlab实现的混沌扰动算法来解决pso算法早熟问题,并用二者结合来训练灰色预测模型参数.rar

    基于matlab实现的活性污泥模型的计算中进水水质转化的源代码.rar

    基于matlab实现的活性污泥模型的计算中进水水质转化的源代码.rar

    node-v5.7.1.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    使用Fcn UNet训练防焊无开口-python源码.zip

    使用Fcn UNet训练防焊无开口-python源码.zip

    ONNXRuntime部署LSTR基于Transformer实时车道线检测包含C++和Python源码+模型+说明.zip

    ONNXRuntime部署LSTR基于Transformer实时车道线检测包含C++和Python源码+模型+说明.zip

    2021-2010上市公司和讯网社会责任评级CSR-股东员工客户消费者环境社会责任分项评级

    上市公司和讯网社会责任评级CSR-股东责任员工责任客户消费者环境社会责任分项评级 得分(2010-2021年) "中国上市公司-和讯网社会责任数据"是 一份来自和讯网的数据集,它同步并收集了中国上市公司关于社会责任的相关信息。包括了 公司在股东责任、员工责任、供应商客户消费者权益责任、环境责任、社会责任中的表现和 成绩,以反映公司承担社会责任的程度。可以帮助大家了解公司在承担社会责任方面的具体 表现。这对于研究公司社会责任与公司业绩、公司声誉、公司风险等方面的关系具有参考意 义。 一、数据介绍 数据名称:上市公司和讯网社会责任评级CSR-股东责任员工责任 客户消费者环境社会责任分项评级得分 数据年份:2010-2021年 样本数量:每 年含2300-4600左右上市公司数据,总数据量40058条(注:因披露口径原因 ,2021年仅有430+上市公司数据) 数据格式:Excel面板数据 二、指标说 明 共计11个指标:股票名称、股票代码、年份、总得分、等级、股东责任、员工责任、 供应商客户和消费者权益责任、环境责任、社会责任、统计日期 三、部分excel数据 展示

    用Stata怎样检验调节效应和被调节的中介效应:学习课件,数据、程序命令源代码

    用Stata怎样检验调节效应和被调节的中介效应:学习课件,数据、程序命令源代码 自己重新整理,不存在任何版权、争议的商业信息! 用Stata怎样检验调节效应和 被调节的中介效应:学习课件,数据、程序命令源代码 用Stata怎样检验调节效应和 被调节的中介效应:学习课件,数据、程序命令源代码 用Stata怎样检验调节效应和 被调节的中介效应:学习课件,数据、程序命令源代码 用Stata怎样检验调节效应和 被调节的中介效应:学习课件,数据、程序命令源代码

    机械设计导套自动供料机sw18可编辑非常好的设计图纸100%好用.zip

    机械设计导套自动供料机sw18可编辑非常好的设计图纸100%好用.zip

    数学建模比赛知识点介绍.zip

    数学建模 数学建模比赛的知识点非常广泛,涵盖了多个数学领域和实际应用领域。以下是一些常见的数学建模比赛知识点介绍: 线性代数:线性代数是数学建模中非常重要的基础知识,包括矩阵运算、线性方程组、向量空间、特征值和特征向量等。这些知识点在解决优化问题、控制系统、信号处理等领域都有广泛应用。 微积分:微积分是数学建模中另一个重要的基础知识,包括函数的极限、导数、微分、积分等。微积分在物理、工程、经济等领域都有广泛应用,例如解决动力学问题、优化问题、概率统计问题等。 概率论与数理统计:概率论和数理统计是数学建模中处理不确定性和随机性的重要工具。这包括随机变量、概率分布、随机过程、假设检验、回归分析、方差分析等。这些知识点在风险评估、市场预测、质量控制等领域都有广泛应用。

    IEC 60947-9-1-2019 低压开关设备和控制设备第9-1部分:主动电弧故障缓解系统灭弧装置.pdf

    IEC 60947-9-1-2019 低压开关设备和控制设备第9-1部分:主动电弧故障缓解系统灭弧装置.pdf

    node-v10.19.0-linux-arm64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    机械设计全自动进料插件机sw18非常好的设计图纸100%好用.zip

    机械设计全自动进料插件机sw18非常好的设计图纸100%好用.zip

    豪华版XX主数据管理解决方案(63页).ppt

    【豪华版】XX主数据管理解决方案(63页).ppt

    node-v4.3.2.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    城市表层土壤重金属污染分析方案设计以及结果分析.doc

    本文档是课题研究的研究报告内含调研以及源码设计以及结果分析

    仿GoMobile触屏版html5响应式手机app网站模板下载-懒人模板.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

    手机159彩触屏版手机wap用户登陆注册模板.zip

    触屏版自适应手机wap软件网站模板 触屏版自适应手机wap软件网站模板

Global site tag (gtag.js) - Google Analytics