说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Android开发进阶之NIO非阻塞包(八)

HTML文档下载 WORD文档下载 PDF文档下载
Android开发进阶之NIO非阻塞包(八)

作者:Android开发网


   在整个DDMS中体现Android NIO主要框架的要数MonitorThread.java这个文件了,有关PC和Android手机同步以及NIO非阻塞编程的精髓可以在下面的文件中充分体现出来。

  final class MonitorThread extends Thread {

    private static final int CLIENT_READY = 2;

    private static final int CLIENT_DISCONNECTED = 3;

    private volatile boolean mQuit = false;

    private ArrayList<Client> mClientList; //用一个数组保存客户端信息

    private Selector mSelector;

    private HashMap<Integer, ChunkHandler> mHandlerMap; //这里Android123提示大家,由于在多线程中concurrentHashMap效率比HashMap更安全高效,推荐使用并发库的这个替代版本。

    private ServerSocketChannel mDebugSelectedChan; //一个用于调试的服务器通道

    private int mNewDebugSelectedPort;

    private int mDebugSelectedPort = -1;

    private Client mSelectedClient = null;

    private static MonitorThread mInstance;

    private MonitorThread() {
        super("Monitor");
        mClientList = new ArrayList<Client>();
        mHandlerMap = new HashMap<Integer, ChunkHandler>();

        mNewDebugSelectedPort = DdmPreferences.getSelectedDebugPort();
    }

    static MonitorThread createInstance() {  //创建实例
        return mInstance = new MonitorThread();
    }

    static MonitorThread getInstance() { //获取实例
        return mInstance;
    }

    synchronized void setDebugSelectedPort(int port) throws IllegalStateException { //设置调试端口号
        if (mInstance == null) {
            return;
        }

        if (AndroidDebugBridge.getClientSupport() == false) {
            return;
        }

        if (mDebugSelectedChan != null) {
            Log.d("ddms", "Changing debug-selected port to " + port);
            mNewDebugSelectedPort = port;
            wakeup(); //这里用来唤醒所有的Selector
        } else {
            // we set mNewDebugSelectedPort instead of mDebugSelectedPort so that it's automatically
            mNewDebugSelectedPort = port;
        }
    }

    synchronized void setSelectedClient(Client selectedClient) {
        if (mInstance == null) {
            return;
        }

        if (mSelectedClient != selectedClient) {
            Client oldClient = mSelectedClient;
            mSelectedClient = selectedClient;

            if (oldClient != null) {
                oldClient.update(Client.CHANGE_PORT);
            }

            if (mSelectedClient != null) {
                mSelectedClient.update(Client.CHANGE_PORT);
            }
        }
    }

    Client getSelectedClient() {
        return mSelectedClient;
    }

    boolean getRetryOnBadHandshake() {
        return true; // TODO? make configurable
    }

    Client[] getClients() {
        synchronized (mClientList) {
            return mClientList.toArray(new Client[0]);
        }
    }

    synchronized void registerChunkHandler(int type, ChunkHandler handler) {
        if (mInstance == null) {
            return;
        }

        synchronized (mHandlerMap) {
            if (mHandlerMap.get(type) == null) {
                mHandlerMap.put(type, handler);
            }
        }
    }

    @Override
    public void run() { //本类的主要线程
        Log.d("ddms", "Monitor is up");

        try {
            mSelector = Selector.open();
        } catch (IOException ioe) {
            Log.logAndDisplay(LogLevel.ERROR, "ddms",
                    "Failed to initialize Monitor Thread: " + ioe.getMessage());
            return;
        }

        while (!mQuit) {

            try {
                synchronized (mClientList) {
                }

                try {
                    if (AndroidDebugBridge.getClientSupport()) {
                        if ((mDebugSelectedChan == null ||
                                mNewDebugSelectedPort != mDebugSelectedPort) &&
                                mNewDebugSelectedPort != -1) {
                            if (reopenDebugSelectedPort()) {
                                mDebugSelectedPort = mNewDebugSelectedPort;
                            }
                        }
                    }
                } catch (IOException ioe) {
                    Log.e("ddms",
                            "Failed to reopen debug port for Selected Client to: " + mNewDebugSelectedPort);
                    Log.e("ddms", ioe);
                    mNewDebugSelectedPort = mDebugSelectedPort; // no retry
                }

                int count;
                try {
                    count = mSelector.select();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                    continue;
                } catch (CancelledKeyException cke) {
                    continue;
                }

                if (count == 0) {
                    continue;
                } //这里代码写的不是很好,Android开发网提示大家因为这个NIO是DDMS工作在PC端的还不明显,这样轮训的在一个while中,效率不是很高,CPU很容易占用率很高。

                Set<SelectionKey> keys = mSelector.selectedKeys();
                Iterator<SelectionKey> iter = keys.iterator(); //使用迭代器获取这个选择键

                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    iter.remove();

                    try {
                        if (key.attachment() instanceof Client) { //判断收到的key的附件是否是Client的实例
                            processClientActivity(key);
                        }
                        else if (key.attachment() instanceof Debugger) { //如果是Debug实例
                            processDebuggerActivity(key);
                        }
                        else if (key.attachment() instanceof MonitorThread) {
                            processDebugSelectedActivity(key);
                        }
                        else {
                            Log.e("ddms", "unknown activity key");
                        }
                    } catch (Exception e) {
                        Log.e("ddms", "Exception during activity from Selector.");
                        Log.e("ddms", e);
                    }
                }
            } catch (Exception e) {
                Log.e("ddms", "Exception MonitorThread.run()");
                Log.e("ddms", e);
            }
        }
    }

    int getDebugSelectedPort() {
        return mDebugSelectedPort;
    }

    private void processClientActivity(SelectionKey key) {
        Client client = (Client)key.attachment();

        try {
            if (key.isReadable() == false || key.isValid() == false) {
                Log.d("ddms", "Invalid key from " + client + ". Dropping client.");
                dropClient(client, true /* notify */);
                return;
            }

            client.read();

            JdwpPacket packet = client.getJdwpPacket();
            while (packet != null) {
                if (packet.isDdmPacket()) {
                    // unsolicited DDM request - hand it off
                    assert !packet.isReply();
                    callHandler(client, packet, null);
                    packet.consume();
                } else if (packet.isReply()
                        && client.isResponseToUs(packet.getId()) != null) {
                    // reply to earlier DDM request
                    ChunkHandler handler = client
                            .isResponseToUs(packet.getId());
                    if (packet.isError())
                        client.packetFailed(packet);
                    else if (packet.isEmpty())
                        Log.d("ddms", "Got empty reply for 0x"
                                + Integer.toHexString(packet.getId())
                                + " from " + client);
                    else
                        callHandler(client, packet, handler);
                    packet.consume();
                    client.removeRequestId(packet.getId());
                } else {
                    Log.v("ddms", "Forwarding client "
                            + (packet.isReply() ? "reply" : "event") + " 0x"
                            + Integer.toHexString(packet.getId()) + " to "
                            + client.getDebugger());
                    client.forwardPacketToDebugger(packet);
                }

                packet = client.getJdwpPacket();
            }
        } catch (CancelledKeyException e) { //注意正确处理这个异常
            dropClient(client, true /* notify */);
        } catch (IOException ex) {
            dropClient(client, true /* notify */);
        } catch (Exception ex) {
            Log.e("ddms", ex);

            dropClient(client, true /* notify */);

            if (ex instanceof BufferOverflowException) { //可能存在缓冲区异常
                Log.w("ddms",
                        "Client data packet exceeded maximum buffer size "
                                + client);
            } else {
                // don't know what this is, display it
                Log.e("ddms", ex);
            }
        }
    }

    private void callHandler(Client client, JdwpPacket packet,
            ChunkHandler handler) {

        // on first DDM packet received, broadcast a "ready" message
        if (!client.ddmSeen())
            broadcast(CLIENT_READY, client);

        ByteBuffer buf = packet.getPayload();
        int type, length;
        boolean reply = true;

        type = buf.getInt();
        length = buf.getInt();

        if (handler == null) {
            // not a reply, figure out who wants it
            synchronized (mHandlerMap) {
                handler = mHandlerMap.get(type);
                reply = false;
            }
        }

        if (handler == null) {
            Log.w("ddms", "Received unsupported chunk type "
                    + ChunkHandler.name(type) + " (len=" + length + ")");
        } else {
            Log.d("ddms", "Calling handler for " + ChunkHandler.name(type)
                    + " [" + handler + "] (len=" + length + ")");
            ByteBuffer ibuf = buf.slice();
            ByteBuffer roBuf = ibuf.asReadOnlyBuffer(); // enforce R/O
            roBuf.order(ChunkHandler.CHUNK_ORDER);
            synchronized (mClientList) {
                handler.handleChunk(client, type, roBuf, reply, packet.getId());
            }
        }
    }

    synchronized void dropClient(Client client, boolean notify) {
        if (mInstance == null) {
            return;
        }

        synchronized (mClientList) {
            if (mClientList.remove(client) == false) {
                return;
            }
        }
        client.close(notify);
        broadcast(CLIENT_DISCONNECTED, client);

        /*
         * http://forum.java.sun.com/thread.jspa?threadID=726715&start=0
         * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5073504
         */
        wakeup();
    }

    /*
     * Process activity from one of the debugger sockets. This could be a new
     * connection or a data packet.
     */
    private void processDebuggerActivity(SelectionKey key) {
        Debugger dbg = (Debugger)key.attachment();

        try {
            if (key.isAcceptable()) { //处理Server响应这个事件
                try {
                    acceptNewDebugger(dbg, null);
                } catch (IOException ioe) {
                    Log.w("ddms", "debugger accept() failed");
                    ioe.printStackTrace();
                }
            } else if (key.isReadable()) { //如果是收到的数据,则可读取
                processDebuggerData(key);
            } else {
                Log.d("ddm-debugger", "key in unknown state");
            }
        } catch (CancelledKeyException cke) { //记住,NIO处理这个异常,很多入门的开发者很容易忘记
            // key has been cancelled we can ignore that.
        }
    }

     private void acceptNewDebugger(Debugger dbg, ServerSocketChannel acceptChan) //这里用到了阻塞方式
            throws IOException {

        synchronized (mClientList) {
            SocketChannel chan;

            if (acceptChan == null)
                chan = dbg.accept();
            else
                chan = dbg.accept(acceptChan);

            if (chan != null) {
                chan.socket().setTcpNoDelay(true);

                wakeup();

                try {
                    chan.register(mSelector, SelectionKey.OP_READ, dbg);
                } catch (IOException ioe) {
                    // failed, drop the connection
                    dbg.closeData();
                    throw ioe;
                } catch (RuntimeException re) {
                    // failed, drop the connection
                    dbg.closeData();
                    throw re;
                }
            } else {
                Log.w("ddms", "ignoring duplicate debugger");
            }
        }
    }

    private void processDebuggerData(SelectionKey key) {
        Debugger dbg = (Debugger)key.attachment();

        try {
            dbg.read();

            JdwpPacket packet = dbg.getJdwpPacket();
            while (packet != null) {
                Log.v("ddms", "Forwarding dbg req 0x"
                        + Integer.toHexString(packet.getId()) + " to "
                        + dbg.getClient());

                dbg.forwardPacketToClient(packet);

                packet = dbg.getJdwpPacket();
            }
        } catch (IOException ioe) {
            Log.d("ddms", "Closing connection to debugger " + dbg);
            dbg.closeData();
            Client client = dbg.getClient();
            if (client.isDdmAware()) {
                   Log.d("ddms", " (recycling client connection as well)");

                    client.getDeviceImpl().getMonitor().addClientToDropAndReopen(client,
                        IDebugPortProvider.NO_STATIC_PORT);
            } else {
                Log.d("ddms", " (recycling client connection as well)");
                // we should drop the client, but also attempt to reopen it.
                // This is done by the DeviceMonitor.
                client.getDeviceImpl().getMonitor().addClientToDropAndReopen(client,
                        IDebugPortProvider.NO_STATIC_PORT);
            }
        }
    }

    private void wakeup() {
        mSelector.wakeup();
    }

    synchronized void quit() {
        mQuit = true;
        wakeup();
        Log.d("ddms", "Waiting for Monitor thread");
        try {
            this.join();
            // since we're quitting, lets drop all the client and disconnect
            // the DebugSelectedPort
            synchronized (mClientList) {
                for (Client c : mClientList) {
                    c.close(false /* notify */);
                    broadcast(CLIENT_DISCONNECTED, c);
                }
                mClientList.clear();
            }

            if (mDebugSelectedChan != null) {
                mDebugSelectedChan.close();
                mDebugSelectedChan.socket().close();
                mDebugSelectedChan = null;
            }
            mSelector.close();
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        mInstance = null;
    }

    synchronized void addClient(Client client) {
        if (mInstance == null) {
            return;
        }

        Log.d("ddms", "Adding new client " + client);

        synchronized (mClientList) {
            mClientList.add(client);

            try {
                wakeup();

                client.register(mSelector);

                Debugger dbg = client.getDebugger();
                if (dbg != null) {
                    dbg.registerListener(mSelector);
                }
            } catch (IOException ioe) {
                // not really expecting this to happen
                ioe.printStackTrace();
            }
        }
    }

    /*
     * Broadcast an event to all message handlers.
     */
    private void broadcast(int event, Client client) {
        Log.d("ddms", "broadcast " + event + ": " + client);

        /*
         * The handler objects appear once in mHandlerMap for each message they
         * handle. We want to notify them once each, so we convert the HashMap
         * to a HashSet before we iterate.
         */
        HashSet<ChunkHandler> set;
        synchronized (mHandlerMap) {
            Collection<ChunkHandler> values = mHandlerMap.values();
            set = new HashSet<ChunkHandler>(values);
        }

        Iterator<ChunkHandler> iter = set.iterator();
        while (iter.hasNext()) {
            ChunkHandler handler = iter.next();
            switch (event) {
                case CLIENT_READY:
                    try {
                        handler.clientReady(client);
                    } catch (IOException ioe) {
                        // Something failed with the client. It should
                        // fall out of the list the next time we try to
                        // do something with it, so we discard the
                        // exception here and assume cleanup will happen
                        // later. May need to propagate farther. The
                        // trouble is that not all values for "event" may
                        // actually throw an exception.
                        Log.w("ddms",
                                "Got exception while broadcasting 'ready'");
                        return;
                    }
                    break;
                case CLIENT_DISCONNECTED:
                    handler.clientDisconnected(client);
                    break;
                default:
                    throw new UnsupportedOperationException();
            }
        }

    }

    /**
     * Opens (or reopens) the "debug selected" port and listen for connections.
     * @return true if the port was opened successfully.
     * @throws IOException
     */
    private boolean reopenDebugSelectedPort() throws IOException {

        Log.d("ddms", "reopen debug-selected port: " + mNewDebugSelectedPort);
        if (mDebugSelectedChan != null) {
            mDebugSelectedChan.close();
        }

        mDebugSelectedChan = ServerSocketChannel.open();
        mDebugSelectedChan.configureBlocking(false); // required for Selector

        InetSocketAddress addr = new InetSocketAddress(
                InetAddress.getByName("localhost"), //$NON-NLS-1$
                mNewDebugSelectedPort);
        mDebugSelectedChan.socket().setReuseAddress(true); // enable SO_REUSEADDR

        try {
            mDebugSelectedChan.socket().bind(addr);
            if (mSelectedClient != null) {
                mSelectedClient.update(Client.CHANGE_PORT);
            }

            mDebugSelectedChan.register(mSelector, SelectionKey.OP_ACCEPT, this);

            return true;
        } catch (java.net.BindException e) {
            displayDebugSelectedBindError(mNewDebugSelectedPort);

            // do not attempt to reopen it.
            mDebugSelectedChan = null;
            mNewDebugSelectedPort = -1;

            return false;
        }
    }

    /*
     * We have some activity on the "debug selected" port. Handle it.
     */
    private void processDebugSelectedActivity(SelectionKey key) {
        assert key.isAcceptable();

        ServerSocketChannel acceptChan = (ServerSocketChannel)key.channel();

        /*
         * Find the debugger associated with the currently-selected client.
         */
        if (mSelectedClient != null) {
            Debugger dbg = mSelectedClient.getDebugger();

            if (dbg != null) {
                Log.d("ddms", "Accepting connection on 'debug selected' port");
                try {
                    acceptNewDebugger(dbg, acceptChan);
                } catch (IOException ioe) {
                    // client should be gone, keep going
                }

                return;
            }
        }

        Log.w("ddms",
                "Connection on 'debug selected' port, but none selected");
        try {
            SocketChannel chan = acceptChan.accept();
            chan.close();
        } catch (IOException ioe) {
            // not expected; client should be gone, keep going
        } catch (NotYetBoundException e) {
            displayDebugSelectedBindError(mDebugSelectedPort);
        }
    }

    private void displayDebugSelectedBindError(int port) {
        String message = String.format(
                "Could not open Selected VM debug port (%1$d). Make sure you do not have another instance of DDMS or of the eclipse plugin running. If it's being used by something else, choose a new port number in the preferences.",
                port);

        Log.logAndDisplay(LogLevel.ERROR, "ddms", message);
    }
}

  从上面来看Android的开源代码有关PC上的写的不是很好,很多实现的地方都是用了严重的缝缝补补方式解决,有些习惯不是很到位,有关本NIO例子由于涉及的项目对象多,理解需要网友深入分析DDMS源码中的每个对象。细节写的不是很理想,Android123推荐大家,画出UML后再分析更清晰。

小米游戏中心月度报告:极品、神庙、找你妹 中科院:常温下的液态金属电路3D打印机 细数IE10里的HTML5特性 使用Twitter Bootstrap的五大理由 Twitter重塑API战略 开启V1.1时代 Sony开放SmartWatch 支持第三方定制固件 甩啦甩啦!Apptopia帮开发者在线买卖App所有权 聚焦全球移动市场:印度,这块肥肉不太肥 Google决定明年一月份停止对Chrome Frame支持与更新 你应该关注的几个Eclipse超酷插件 华为王丰:FusionCube打造下一代融合一体机 上海云人联合创始人吴朱华:中国人也能做出最好的实时数据库产品 Facebook RSS替代Google Reader?或因其社交属性失败 让这么多国外开发者如此兴奋,iOS 7到底好在哪里? Web开发中那些不招人“待见”的功能 最好的超级计算机在中国 为开发者提供的10款Web应用程序 5000万次下载:HandyGames如何征服Google Play? 红帽大战Ubuntu:750小时免费企业版红帽套餐即将登陆AWS EMC Sanjay Mirchandani:92%虚拟化,使更少IT人拥有更大交付能力 从NSA携谷歌、微软等9家名企监控用户行为看数据安全 【专访间】新科兰德创始人左磊:我们的“卖点”是“数据弹药” 甲骨文公司宣布推出最新Java EE 7 10款最佳CSS/jQuery开源图片说明 创业者应避免对投资者说的五句话 直接拿来用!最火的iOS开源项目(二) 西部数据Pat Wilkison:云计算市场是创新热点 猎豹浏览器发布手机版:PM谈开发理念 成为伟大开发者的“九步曲” 使用GPU构建更便宜的Google神经网络 Facebook与Yahoo!的“火花”:系统间实时数据流管理工具 请大家推荐一个短信网关 调查:当你身边响起神圣的国歌时,你会不会不由自主站起来,手放到胸前,跟着节奏一起唱起来?(有感而发) 请问如何调用.chm的帮助文件? 如何调用系统默认打印机的属性! 请教新手问题~~~麻烦哪为大侠给解释解释~谢~ 如何用struts实现阴阳色列表? 怎么用vb建立一个数据库呀?注意,不是一个表,是一个数据库! 如何调用系统默认打印机的属性! 一个很老很过时的数码相机。 郁闷,超级简单题目 初学ASP,请教学习心得 我的机器怎么老死机?? 两级表单动态联接?急,急,急!!!!!????? ---见了鬼了,Jre不好用!!!--- 寻求把中文字符串转换为十六进制的串的ORACLE函数? 电力学院惊魂 一條語句 數據庫日誌就寫滿了 怎样获得系统的字体!急!谢谢了! 谁有用java做的聊天系统程序(当作业)分不够可再给 在CB中如何动态的管理窗体 如何调用系统默认打印机的属性! API动态调用问题(很奇观) 好久没有发帖子了,现在心情奇好,兄弟们来接分! 在CB中如何动态的管理窗体 求C#网络编程书籍下载~ 简单问题,在线等待。可以在加分。 请教一题目! thanks sdany java 中能不能实现一个数字键盘 关于重定位 菜菜问题:让VB画出sin(x)和log(x)的函数图象怎么做?刚学VB的,x可以取任意的值! thanks sdy 模拟鼠标键???? 弱智问题,请原谅 我需要帮助~~~~!!!!! 请教:用LoadImage()载入的光标资源,当光标尺寸大于32*32时,显示不正常? cls 怎么用??? 请问<%=type2(RS("qi_type2"))%> 是什么意思? 招ASP程序员,工作地点杭州. ORACLE9i中的storage怎么不起作用了? 评评<<离散数学及其应用>>.我有些题目不会做呀.比如和费马小定理有关的.呵呵 谁能告诉我程序员考试是每年的什么时候啊?? 声音设备问题? 关于字符串输出 利用VB写SQL语句的问题(实现删除功能) 太岁灭城 晋中鬼事之二 (书雅) 有关上传数据库的问题? asc码为13的在jsp里用什么表示? GetCurSorPos声明在哪里? 信誉值怎么升高?怎样提高可用分?我的分太少了! help:中文字段update出错 第四题,按有效数字运算! 霞霞不听话好看的繁体字 求具体过程及答案 给假字换个偏旁,组成另外的字填在括号里.天空中那美丽的( )常常引得我驻足观赏 The man had had an uncomfortable trip.He was very hungry.(not only……but……as well)用括号中的连词改写上面的句子,具体说啊, 支离破碎这个词语有什么样意思!代表什么!它的意思 在一次“模拟微重力环境”的实验中,实验人员乘座实验飞艇到达6000m的高空,然后让其由静止下落,下落过程中飞艇所受空气阻力为其重力的0.04倍,实验人员可以在飞艇内进行微重力影响的实验 画一张画,和一篇作文! 急死了不知道到明天晚上有没有回答,所以先放20分,有人回答,并且我满意的加50!言归正传,我所学的是哲学基础知识(第二版),高等教育出版社的.都是辨析题,然你说明下面的是否正确.1:追 请问“失乐园”的英文是什么? 为了观赏美丽的苍穹,每一个人都应当选择降生 这句话怎么理解有人曾问古希腊思想家阿那克萨哥拉,一个人是否应该来到这个世界.阿那克萨哥拉抬头仰望着夜空,笑着说:“为了观赏美丽的 the man had had an uncomfortable trip.he was very hungery (not only-but-as well)he had not eaten anything for thirteen hours.he had not drink anything for thirteen hours(neither-nor)wollen goods cannot be eaten.at least they are soft.the man had had 唐伯虎的《桃花庵歌》的全译是什么? 一倾角为30度的斜面放置在粗糙的水平面上,质量m=4kg的物体以a=3m/s^2的加速度沿斜面下滑,而斜面体M保持相对静止,求M于地面的摩擦力大小答案是6倍的根号3额! 假如说我今天用望远镜看见10E光年一个星球爆炸,那是10E光年钱的事情吗? 唐寅的桃花庵歌赏析正常赏析+除了表现他超脱避世的方面,还能不能表现出他还是无法摆脱仕途的幻想之类的呢?他人笑我太疯癫,我笑他人看不穿真的是他看透了一切吗?还是他也看不穿呐?请 为什么汽车定位比手机定位快 一物生来真奇怪,它是世界一盘菜,娘死以后它才生,它死以后娘还在.(打一微生物) 日全食旁边光环叫什么 诺曼底号遇难记读后感j急 “一切恩爱会,无常难得久.生世多畏惧,命危于晨露.因爱故生忧,因爱故生怖.若离于爱者,无忧亦无怖. 日全食时为什么会有光环套住.就是圆的周围为什么会有亮光.圆环套住.按理说 是整个太阳被月亮遮住 应该 都没光的 怎么还有个圆环.就是被遮住的地区都没光的啊.还有太阳被遮住应该会挺 Be early to.还是 be early for 由爱故生忧,由爱故生怖.若离于爱者,无忧亦无怖. 水处理中树脂主要去除什么东西 try to be 求求你们了一根电阻丝的电阻为R=16欧姆,将他做成正方形求(1)A B两点间电阻R AB为多少欧姆?(2)AC两点之间电阻RAB为多少欧姆? 数学的本质是什么 诺曼底号遇难记读后感五年级水平 假如战斗机在飞行当中突然爆炸,此时的飞行员没有来得及跳伞,那么这个飞行员还有没有生还的可能了?XIE XIE HUI DA. 什么是数学本质 be early和early有意思和词性上的区别吗be early是短语吗?是固定搭配吗?---------------------------------He is always early for workHe always finish homework early上面两句表述都对吗? 有关光电效应的一个问题什么是光电效应的阻遏电位(即stopping potential)啊?谁能给解释下. 数学的本质是自由如何理解? 如何通过实验确定各转录因子的功能? 小丽每分钟跳绳160下,小李每分钟跳的数量比小红少九分之一,比小华多七分之一.求小红和小华每分钟各跳多少下 数学的规律是什么?数学的本质是什么? 诺曼底号遇难记读后感300字,急 bonus和dividend的区别?请不要复制词典的内容!最好给出一些例子来, 数学本质数学的本质? 2 3小题,写纸上,先答先采纳, 如何区分INTEREST的两种意思INTEREST什么时候表达利益的意思,什么时候表达兴趣~以前老师也说单复数,但我在书上看到一句不同的兴趣是"DIFFERENT INTERESTS".对了,还有,表达兴趣的INTEREST一定是不可 I left school early yesterday ____ the weather got worse in the afternoon【填介词、副词或连词】 did you leave the park early yesterday afternoon?no,I__there___it was closed.A left;before B stayed;until C was staying;after D was leaving;until dividend与divedent的区别equals 与equal,equation的区别 easier said than done中的said和done为什么要用过去分词 日记快 可变成本与不可变成本的含义 我想要一滴水,没想到您给我整个海洋;我想要一片云,没想到您给我整个蓝天;是哪首歌的词? 韩式如何画眉毛 固定成本和可变成本的问题当产量增加时,单位产量上摊销的固定成本就会减少,而可变成本不发生变化,其总成本将减少? 滋润脊髓神经的液体叫什么? 关于光电效应的一道题“若激光束射入玻璃球之前能使某种金属发生光电效应现象,通过玻璃球时由于有能量损失,穿越玻璃球后射出就有可能不能使该金属发生光电效应现象”这句话为什么 以下哪些是可变成本,哪些是固定成本?外购原材料,外购燃料及动力,工资及福利,修理费,折旧费,摊销费,财务费用,其他费用哪些是可变成本,哪些是固定成本?如果折旧和摊销都采用直线折旧法 afternoon是什么意思 霞用韩国文字怎么写 总成本包括固定成本和可变成本, 天空中那美丽的(),常常引得我驻足观赏给“假”字换个偏旁,组成另外个字····谢谢 天上的彩虹,什么万丈,好看极了.用霞组词 支离破碎的意思 日本万圣节:“僵尸”涌上街头占领东京空气污染致癌 波兰致力于减少碳排放美参院情报委拟法案缩减监听记录 被批原吉林省常务副省长田学仁受贿1919嘉兴消防严查7家液氨企业 清剿火患2在建工地内工棚突发大火 杭州滨江消防杭州疾控举行卫生应急联合演习 “全副武义一店铺发生火灾爆炸事故 消防成功勒紧腰带节俭办展 浙江临海户外休闲用菲人质事件赔偿谈判开启 马尼拉代表语俄媒:中美等十余国将参与2014年在奥巴马出席投资美国峰会 游说外商投资日韩两国或围绕慰安妇问题大闹法国国际朴槿惠称决不容忍腐败 要求根除核电腐日俄拟举行联合军演 被指意遏制中国进法媒称4名被绑法国人雇主为救人交付高美国将建全球最高摩天轮 超越伦敦眼西班牙走出两年经济衰退 首次出现经济俄副总理:俄能够在举办冬奥会的同时保美国指责德国过度依赖出口危害世界经济俄罗斯富人与穷人代名词:寡头、工薪族九哥双11媒体狂欢节,分分钟让你上头请听脑洞题:工农中建那么大,如果倒了多几个公众号、多几个看世界的视角|推感谢剁手党和房奴,你们造就了亚洲足球论金融男如何脱离低级趣味李源潮与印度副总统安萨里会谈3500点之上,一个危险的信号一篇泽熙推荐给操盘手的文章东营黄河口成国家一级保护鸟类白鹤迁徙法国侨界期待“习马会” 热评对两岸关乔振宇挑战绕口令获封“最炫舌神” 河北举行高云升先进事迹报告会 从警近吴亦凡忆剃头趣事:镜子里看到我的头就7张图看懂中国富豪资本出逃的秘术最近5年中国人口的迁徙浪潮(影响每一晚餐怎么吃能减肥 4个习惯让你瘦成一基美影业高敬东:中美电影合作的“信任“以笔抒怀写人生”——书法家唐庭伯身为男人,减肥健身怎能不考虑一下胸肌专业干货!图表解析资产减值准备你很累,不自由,各种不如意,是因为你
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘