??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲激情视频在线,丝瓜av网站精品一区二区,日韩在线三区http://www.aygfsteel.com/jelver/articles/329171.html冰河快狼冰河快狼Tue, 17 Aug 2010 23:59:00 GMThttp://www.aygfsteel.com/jelver/articles/329171.htmlhttp://www.aygfsteel.com/jelver/comments/329171.htmlhttp://www.aygfsteel.com/jelver/articles/329171.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/329171.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/329171.html 在h人网量存储pȝ的存储引擎部分,Z提高CPU和网l的使用情况Q用了ja...  阅读全文

冰河快狼 2010-08-18 07:59 发表评论
]]>
java nio在多U程环境需注意的问?/title><link>http://www.aygfsteel.com/jelver/articles/322212.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sat, 29 May 2010 07:53:00 GMT</pubDate><guid>http://www.aygfsteel.com/jelver/articles/322212.html</guid><wfw:comment>http://www.aygfsteel.com/jelver/comments/322212.html</wfw:comment><comments>http://www.aygfsteel.com/jelver/articles/322212.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/jelver/comments/commentRss/322212.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/jelver/services/trackbacks/322212.html</trackback:ping><description><![CDATA[<p>原帖Q?a>http://www.aygfsteel.com/adapterofcoms/archive/2010/03/02/314242.html</a><br /> <br /> 有h说java nio在多U程环境下编E简直就是个恶梦,其实你如果能把握住java nio API的要?你就可以之N. </p> <p>0. 一?channal 对应一个SelectionKey in the same selector.<br /> e.g: <br /> SelectionKey sk=sc.register(selector, SelectionKey.OP_READ, handler);<br /> sk==sc.register(selector, SelectionKey.OP_WRITE, handler) true?<br /> selector.select() 每次q回的对同一channal的sk是否相同? </p> <p>1.channel.register(...) may <strong>block</strong> if invoked concurrently with another registration[another.register(...)] or selection operation[selector.select(...)] involving *****<strong>the same selector</strong>*****.<br /> q个是registerҎjdk src上的原文,<br /> e.g:<br /> 如果一个selection thread已经在selectҎ上等待ing,那么q个时候如果有另一条线E调用channal.registerҎ的话,那么它将被blocking.<br /> <br /> 2.selectionKey.cancel() : The key will be <strong>removed</strong> from all of the selector's key sets <strong>during</strong> *****<strong>the next selection operation[selector.select(...)]</strong>*****.<br /> may <strong>block</strong> briefly if invoked concurrently with a cancellation[cancel()] or selection operation[select(...)] involving ***<strong>the same selector</strong>***.<br /> q个也是cancelҎjdk src上的原文,<br /> e.g:<br /> 你先一个selectionKey.cancel(),然后随即再channel.register to <strong>the same selector</strong>,<br /> 在cancel和register之间,如果没有U程(包括当前U程)q行select操作的话,<br /> 那么 throws java.nio.channels.CancelledKeyException.<br /> 所?nbsp;cancel-->select-->re-register.  </p> <p>3.if <strong>don't remove</strong> the current selectedKey from selector.selectedKeys()[Set] 导?selector.select(...) <strong>not</strong> <strong>block</strong> [may be cpu 100%,specially when client cut the current channel(connection)].<br /> e.g:<br /> Iterator<SelectionKey> it=selector.selectedKeys().iterator();<br /> ...for/while it.hasNext()...<br /> it.remove();<strong><------*****must do it. or Keys' Set.clear() finally;</strong> </p> <p>if remove the current selectedKey from selector.selectedKeys()[Set] <strong>but don't</strong> <strong>sk.interestOps(sk.interestOps()& (~sk.readyOps()))</strong>;导?selector.select(...) <strong>not block</strong> [select() not block several times, or excepted exception] </p> <p>4.op_write should not be registered to the selector.   [may be cpu100%] </p> <p>5. if involving  wakeup() <strong>before</strong> select() [wakeup called several times >=1],the <strong>next</strong> select() <strong>not block</strong> [not block just once]. </p> <p>管以前有些人分析了nio的wakeup性能及not block in linux的bug,但是java nio依然是高效的,那些c/c++的牛Zȝ看jre/bin目录下的nio.dll/nio.so?java nio是基于select模型(q个是c/c++中常用网l编E模型之一)?</p> <p>Zjava nio的服务器:mina,girzzly[glassfish],jetty(Zgirzzly),tomcat6[可以配置Http11NioProtocol]...</p> <p>其中从本人对girzzly,tomcat6的源码分析来?它们都还没有真正发挥出nio异步处理h的优?它们的读写还都是blocking的虽然用了selectorPool,此外tomcat6要剥dsocket通信q要p一定的功夫.?strong>mina</strong>却是<strong>?font class="" style="font-family: " color="#ff0000">?/font>W其?/strong>,q有<strong>bug</strong>?</p> <p><br />  </p> <img src ="http://www.aygfsteel.com/jelver/aggbug/322212.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/jelver/" target="_blank">冰河快狼</a> 2010-05-29 15:53 <a href="http://www.aygfsteel.com/jelver/articles/322212.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用NIO实现的一个Chat Demo [转]http://www.aygfsteel.com/jelver/articles/322201.html冰河快狼冰河快狼Sat, 29 May 2010 04:38:00 GMThttp://www.aygfsteel.com/jelver/articles/322201.htmlhttp://www.aygfsteel.com/jelver/comments/322201.htmlhttp://www.aygfsteel.com/jelver/articles/322201.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/322201.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/322201.html发现|上扑ֈ的许多NIO的用例在跑v来后都有许多问题Q最常见的就是没有对interest eventq行合理的registry和unregistryQ导致程序一直在looplingQ又或者当客户端或服务器端q接断开时有d@环的q象。忍不住自己做了一个demoQ我惛_以作Z个NIO应用的模板去修改Q只要把doReadQdoWrite之类的用ZU程的Handlerd理,那就基本可以满需求了?br /> q个Demo的目的是在Client和Server间徏立类似QQ聊天那样的功能,让客L和服务器端都支持用户输入和异步消息显C(因ؓ服务器端要支持用Lconsole输入Q所以不要用多个客户端进行连接,否则可能会出现难以预的问题Q?br /> 代码中用U色昄的地Ҏ我认为需要注意的地方Q说老实话NIO虽然很强大,但完全用Non-Blocking来编E,有许多需要小心的地方Q一不小心还可能造成d@环。就像ReentrantLock之于SynchronizedQ如果基本的IO能满需求,׃必强求应用NIO?br /> 注意QOP_WRITE应该是在写入准备qA的时候才d到SelectionKey里面去,而且在写入完成后一定要去除Q否则selector.select()Ҏ׃会被blocking而造成d@环?br />
MyNioServer.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

public class MyNioServer {

    private int BUFFERSIZE = 1024*10;
    private String CHARSET = "GBK";
    private Selector sel;

    public MyNioServer(int port) throws IOException {
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.socket().bind(
                new InetSocketAddress(InetAddress.getLocalHost(), port));
        sel = Selector.open();
        ssc.register(sel, SelectionKey.OP_ACCEPT);
    }

    public void startup() {
        System.out.println("Server start...");
        try {
            while (!Thread.interrupted()) {
                int keysCount = sel.select();
                System.out.println("Catched " + keysCount + " SelectionKeys");
                if (keysCount < 1) {
                    continue;
                }
                Set<SelectionKey> set = sel.selectedKeys();
                Iterator<SelectionKey> it = set.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    if (key.isAcceptable()) {
                        System.out.println("Key isAcceptable");
                        doAccept(key);
                    }
                    if (key.isValid() && key.isReadable()) {
                        System.out.println("Key isReadable");
                        doRead(key);
                    }
                    if (key.isValid() && key.isWritable()) {
                        System.out.println("Key isWritable");
                        doWrite(key);
                    }
                }
                set.clear();
            }
            System.err.println("Program is interrupted.");
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Server stop...");
        shutdown();
    }
   
    public void shutdown(){
        Set<SelectionKey> keys = sel.keys();
        for(SelectionKey key:keys){
            try {
                key.channel().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            sel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void doAccept(SelectionKey key) {
        try {
            SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
            sc.configureBlocking(false);
            SelectionKey newkey = sc.register(sel, SelectionKey.OP_READ);
            newkey.attach(new LinkedList<ByteBuffer>());
            new Thread(new UserInteractive(newkey)).start();
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("Failed to accept new client.");
        }
        System.out.println("end doAccept");
    }

    // TODO buffersize performance testing
    private void doRead(SelectionKey key) {
        try {
            SocketChannel sc = (SocketChannel) key.channel();
            ByteBuffer bb = ByteBuffer.allocate(BUFFERSIZE);
            StringBuffer sb = new StringBuffer();
            int count = 0;
            while ( (count = sc.read(bb)) > 0) {
                bb.flip();
                sb.append(Charset.forName(CHARSET).decode(bb));
                bb.flip();
            }
            //if client disconnected, read return -1
            if(count == -1){
                System.out.println("client disconnected");
                disconnect(key);   
            } else {
                System.out.println("message received from client:" + sb.toString());
            }
        } catch (IOException e) {
            disconnect(key);
            e.printStackTrace();
        }
        System.out.println("end doRead");
    }

    private void doWrite(SelectionKey key) {
        SocketChannel sc = (SocketChannel) key.channel();
        LinkedList<ByteBuffer> outseq = (LinkedList<ByteBuffer>) key
                .attachment();
        ByteBuffer bb = outseq.poll();
        if(bb == null){
            return;
        }
        try {
            while(bb.hasRemaining()){
                sc.write(bb);
            }           
        } catch (IOException e) {
            disconnect(key);
            e.printStackTrace();
        }
        if (outseq.size() == 0) {
            System.out.println("after all buffers wrote, unregister OP_WRITE from interestOps");
            key.interestOps(SelectionKey.OP_READ);
        }
        System.out.println("end doWrote");
    }

    private void disconnect(SelectionKey key) {
        try {
            key.channel().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //TODO find out how to shutdown
    private class UserInteractive implements Runnable {

        SelectionKey key;

        public UserInteractive(SelectionKey key) {
            this.key = key;
        }

        public void run() {
            System.out.println("UserInteractive thread start...");
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    System.in));
            while (true) {
                try {
                    String inputLine = br.readLine();
                    ByteBuffer bb = ByteBuffer.allocate(BUFFERSIZE);
                    bb = ByteBuffer.wrap(inputLine.getBytes());
                    ((LinkedList<ByteBuffer>) key.attachment()).offer(bb);
                    System.out
                            .println("after input, register OP_WRITE to interestOps and wakeup selector");
                    key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                    key.selector().wakeup();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            MyNioServer server = new MyNioServer(10001);
            server.startup();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Exception caught, program exiting…");
        }
    }
}


MyNioClient.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.SelectionKey;
import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.Set;
import java.util.Iterator;

public class MyNioClient {

    private int BUFFERSIZE = 1024*10;
    private String CHARSET = "GBK";
    private Selector sel;

    public MyNioClient(int port) throws IOException {
        SocketChannel sc = SocketChannel.open();
        sc.configureBlocking(false);    // this operation need to be executed before socket.connnect, for OP_CONNECT event
        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(), port));
        sel = Selector.open();
        sc.register(sel, SelectionKey.OP_CONNECT |SelectionKey.OP_READ);
    }

    public void startup() {
        System.out.println("Client start...");
        try {
            while (!Thread.interrupted()) {
                int keysCount = sel.select();
                System.out.println("Catched " + keysCount + " SelectionKeys");
                if (keysCount < 1) {
                    continue;
                }               
                Set<SelectionKey> selectedKeys = sel.selectedKeys();
                Iterator<SelectionKey> it = selectedKeys.iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    //printKeyInfo(key);
                    if (key.isConnectable()) {
                        System.out.println("Key isConnectable");
                        doConnect(key);
                    } else if (key.isValid() && key.isReadable()) {
                        System.out.println("Key isReadable");
                        doRead(key);
                    } else if (key.isValid() && key.isWritable()) {
                        System.out.println("Key isWritable");
                        doWrite(key);
                    }
                }
                selectedKeys.clear();
            }
            System.err.println("Program is interrupted.");
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Client stop...");
        shutdown();
    }
   
    public void shutdown(){
        Set<SelectionKey> keys = sel.keys();
        for(SelectionKey key:keys){
            try {
                key.channel().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            sel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void printKeyInfo(SelectionKey key) {
        String keyStr = MessageFormat
                .format(
                        "IntOps:{0},ReadyOps:{1},isVal:{2},isAcc:{3},isCnn:{4},isRead:{5},isWrite:{6}",
                        key.interestOps(), key.readyOps(), key.isValid(), key
                                .isAcceptable(), key.isConnectable(), key
                                .isReadable(), key.isWritable());
        System.out.println(keyStr);
    }

    private void doConnect(SelectionKey key) {
        try {
            boolean flag = ((SocketChannel) key.channel()).finishConnect();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        System.out.println("unregister OP_CONNECT from interestOps");
        key.interestOps(SelectionKey.OP_READ);
        key.attach(new LinkedList<ByteBuffer>());
        new Thread(new UserInteractive(key)).start();
    }

    private void doRead(SelectionKey key) {
        try {
            SocketChannel sc = (SocketChannel) key.channel();
            ByteBuffer bb = ByteBuffer.allocate(BUFFERSIZE);
            StringBuffer sb = new StringBuffer();
            while (sc.read(bb) > 0) {
                bb.flip();
                sb.append(Charset.forName(CHARSET).decode(bb));
                bb.flip();
            }
            System.out.println("message received from server:" + sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
            disconnect(key);
            System.exit(1);
        }
        System.out.println("now end readMessage");
    }

    private void doWrite(SelectionKey key) {
        SocketChannel sc = (SocketChannel) key.channel();
        LinkedList<ByteBuffer> outseq = (LinkedList<ByteBuffer>) key
                .attachment();
        ByteBuffer bb = outseq.poll();
        if(bb == null){
            return;
        }
        try {
            while(bb.hasRemaining()){
                sc.write(bb);
            }           
        } catch (IOException e) {
            disconnect(key);
            e.printStackTrace();
        }
        if (outseq.size() == 0) {
            System.out.println("after all buffers wrote, unregister OP_WRITE from interestOps");
            key.interestOps(SelectionKey.OP_READ);
        }
        System.out.println("end doWrote");
    }

    private void disconnect(SelectionKey key) {
        try {
            key.channel().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class UserInteractive implements Runnable {

        SelectionKey key;

        public UserInteractive(SelectionKey key) {
            this.key = key;
        }

        public void run() {
            LinkedList<ByteBuffer> outseq = (LinkedList<ByteBuffer>) key
                    .attachment();
             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                try {
                    String inputLine = br.readLine();
                    if ("quit".equalsIgnoreCase(inputLine)) {
                        key.channel().close();
                        System.exit(1);
                        break;
                    }
                    ByteBuffer bb = ByteBuffer.allocate(BUFFERSIZE);
                    bb = ByteBuffer.wrap(inputLine.getBytes());
                    outseq.offer(bb);
                    System.out
                    .println("after input, register OP_WRITE to interestOps and wakeup selector");
                    key.interestOps(SelectionKey.OP_READ
                            | SelectionKey.OP_WRITE);
                    sel.wakeup();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            MyNioClient client = new MyNioClient(10001);
            client.startup();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Exception caught, program exiting...");
        }
    }

}



冰河快狼 2010-05-29 12:38 发表评论
]]>
Java Socket|络~程的经怾??http://www.aygfsteel.com/jelver/articles/280175.html冰河快狼冰河快狼Fri, 05 Jun 2009 03:19:00 GMThttp://www.aygfsteel.com/jelver/articles/280175.htmlhttp://www.aygfsteel.com/jelver/comments/280175.htmlhttp://www.aygfsteel.com/jelver/articles/280175.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/280175.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/280175.html阅读全文

冰河快狼 2009-06-05 11:19 发表评论
]]>
Scalable io in java ?/title><link>http://www.aygfsteel.com/jelver/articles/254389.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 12 Feb 2009 06:35:00 GMT</pubDate><guid>http://www.aygfsteel.com/jelver/articles/254389.html</guid><wfw:comment>http://www.aygfsteel.com/jelver/comments/254389.html</wfw:comment><comments>http://www.aygfsteel.com/jelver/articles/254389.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/jelver/comments/commentRss/254389.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/jelver/services/trackbacks/254389.html</trackback:ping><description><![CDATA[     摘要: 原文http://blog.csdn.net/liu251/archive/2008/07/06/2618752.aspx 本文可看成是对Doug Lea Scalable IO in Java一文的译?当前分布式计 Web Services盛行天下Q这些网l服务的底层都离不开对socket的操作。他们都有一个共同的l构Q?1. Read request 2. Decode reques...  <a href='http://www.aygfsteel.com/jelver/articles/254389.html'>阅读全文</a><img src ="http://www.aygfsteel.com/jelver/aggbug/254389.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/jelver/" target="_blank">冰河快狼</a> 2009-02-12 14:35 <a href="http://www.aygfsteel.com/jelver/articles/254389.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>|络在线游戏开发心?服务器端) 转脓http://www.aygfsteel.com/jelver/articles/239470.html冰河快狼冰河快狼Sat, 08 Nov 2008 15:14:00 GMThttp://www.aygfsteel.com/jelver/articles/239470.htmlhttp://www.aygfsteel.com/jelver/comments/239470.htmlhttp://www.aygfsteel.com/jelver/articles/239470.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/239470.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/239470.html一个多人在U的牌c?a target="_blank">|络游戏的项目͘q尾壎ͼ我参与了该项目的整个设计程Qƈ且完成了90%的核心代码。关于这个项目,有很多地方值得聊一聊。本pd不打把q个目得多么详细规范Q那是设计文档应该描q的Q我打算只说说一些值得注意的地斏V这个项目的一个特别之处是Q客L?a target="_blank">手机Q用户通过Ud|络?a target="_blank">服务?/a>通信。和PC相比Q手机的处理能力极弱Q而且|络量费用昂贵。因为除了要考虑普?a target="_blank">|络游戏的一些问题之外,q两点也需要在设计中充分考虑。首先是开发语a的选择Q由于服务器?a target="_blank">Linux的环境,MS的技术直接排除,至于MONO嘛,我实在不攑ֿ。可供选择的是C++?a target="_blank">JavaQJava胜在|络能力强大Q开发周期短Q有众多框架和开源库的支持,要写出烂得不可接受的代码也不ҎQC++则胜在速度快。综合各斚w因素QC++更容易把q个目变成一堆代码噩梦,我们选择了Java?/span>

一?span style="font: 7pt 'Times New Roman'">             |络

|络游戏Q首先面临的问题当然是如何进行网l通信。首先考虑的是HTTP协议Q因为所有的J2ME手机都支持这个,我们当然惛_可能的兼容用戗而且HTTP协议装E度已经非常高了Q不用去考虑U程、同步、状态管理、连接池Q不qHTTP协议有两个不爽的地方Q?/span>

?nbsp;协议无状态,q个问题已经困扰q很多h很多ơ了。我曾考虑q的解决办法是改造HTTP协议Q在数据传输完成之后不关闭socketQ但是这样做工作量非常大Q在目周期中,基本上就是Mission impossibleQ不予考虑。那么客户也只能通过轮询的方式向服务器请求数据?/span>

?nbsp;|络量q大。就q个目来说Q网l间传递的只是指oQ但是每ơ传递都要加上一堆毫无用处的HTTP HeadQ再加上客户端需要做轮询Q这个流量对于手机来说简直恐怖,l简单测试,按照0.03?K的GPRS|络费用计算Q一局牌居然要消?元多的费用(每秒轮询Q,实在不可接受。也许我们可以采用流量费包月的资Ҏ式,不过q个话题与技术无兟?/span>

以上问题D我们选择了SocketQ这意味着我们没有一?a target="_blank">Web环境Q很多东襉K要靠自己d玎ͼU程理、客L态监控、对象池、控制台……….|络部分打算采用Java NIO来实玎ͼq是一U新的网l监听方式,Z事g的异步通信Q可以提?nobr oncontextmenu="return false" onmousemove="kwM(0)" id="clickeyekey0" onmouseover="kwE(event,0, this)" style="background: url(http://control.clickeye.com.cn/images/line5.gif) repeat-x 50% bottom; padding-bottom: 2px; color: #6600ff" onclick="kwC(event,0)" onmouseout="kwL(event,this)">性能。每个客Lq接之后Q会有一个独立的SocketChannel与它通信Q这个SocketChannel会在用户的整个生存周期中存在。用户如果断开q接Q服务器会得?1Qƈ且会抛出Connection reset异常Q通过捕获q两个特征,可以在用h外断开q接后清理相关的资源。由于NIO是异步通信的,所以没有复杂的U程理?/span>

二?span style="font: 7pt 'Times New Roman'">             通信协议

q个目q没有复杂的通信指oQ命令数量很有限Q但是还是有个关键问题需要关注:量。ؓ了尽量减流量,我们使用字节代替字符串来保存pȝ指oQ这样可以ɋ量减少一半,比如使用一个字节来保存一张扑克牌Q字节高位表CԌ字节低位表示数字Q如?代表黑桃Q那么黑桃三应该是0x03Q这个需要靠位操作来实现Q?/span>

int m=0;

    int n=3;

    byte card=(byte)(m)<<4)|((byte)n;       //m左移四位Q然后与n左或操作

游戏中需要传递用LU分Q这是一个大整数Q用四个字节来保存比较保险Q将整数转换为四个字节的操作如下Q?/span>

 

public static byte[] translateLong(long mark){
    
byte[] b = new byte[4];
    
for (int i = 0; i < 4; i++){
        b[i] 
= (byte) (mark >>> (24 - i * 8));
    }

    
return b;
}

 

四个字节{回来的操作如下:

 

public static long translateByte(byte[] b){
    
int mask = 0xff;
    
int temp = 0;
    
int res = 0;

    
for (int i = 0; i < 4; i++{
        res 
<<= 8;

        temp 
= b[i] & mask;

        res 
|= temp;
    }

    
return res;
}

 

三?span style="font: 7pt 'Times New Roman'">             数据?/a>q接?/span>

׃没有一个web环境Q所以我们需要自己实C个数据库q接池,apache有一个项目叫做commons DBCPQ这是一个基于apache自己的对象池Qapache commons poolQ实现的数据库连接池Q我们可以直接拿来用,apache的Y件未必是最好的Q但是极大可能比我们自己写的要好。Commons DBCP需要三?jarQcommons-collections-3.1.jar、commons-dbcp-1.2.1.jar、commons-pool-1.2.jarq三个文仉可以在apache – Jakarta – commons目?a target="_blank">下蝲Q加入到工程中即可。构造一个数据库q接池的代码如下Q?/span>

 

import java.sql.*;

import com.gwnet.games.antiLord.util.*;

import org.apache.commons.dbcp.ConnectionFactory;

import org.apache.commons.dbcp.BasicDataSource;

import org.apache.commons.dbcp.DataSourceConnectionFactory;

private static BasicDataSource bds=new BasicDataSource();

private static ConnectionFactory fac=null;

 
//初始化连接池

bds.setDriverClassName(“org.postgresql.Driver”); 
//数据库驱动程?/span>

bds.setUrl(“JDBC:postgresql:
//localhost:5432/myDB”); //数据库url

bds.setUsername(“postgres”);                      
//dba帐号

bds.setPassword(“XXXXXXXX”);              
//密码

bds.setInitialSize(
100);                            //初始化连接数?/span>

bds.setMaxIdle(
10);                         //最大idle?/span>

bds.setMaxWait(
1000*60);                        //时回收旉

fac
=new DataSourceConnectionFactory(bds);       //得到q接工厂

Connection conn
=fac.createConnection();         //从池中获得连?/span>

conn.close();                                   
//释放q接Q回到池?br />
//销毁连接池

bds.close();

bds
=null;

fac
=null;

误行处理操作中的各U异常?/span>

四?span style="font: 7pt 'Times New Roman'">             扑克牌的生成

游戏中需要ؓ用户生成随机的扑克牌Q首先我们需要初始化一副牌Q放C个Hashmap中,每张牌以一个字节表C,高ؓ代表pQ的Z表数字,生成整副牌:

private static HashMap cards = new HashMap();

int tmp=0;

for (int i = 0; i <4; i++{

for (int m = 0; m < 13; m++{

tmp
=((byte)(i)<<4)|((byte)m);   //使用位操作构造一张牌

cards.put(
new Integer(i * 13 + m),new Byte((byte)tmp));

}


}


cards.put(
new Integer(53), new Byte((byte)0x4d));   //大王

cards.put(
new Integer(54), new Byte((byte)0x4e));   //

如何随机地得到其中的N张牌呢?我们的做法是生成一?-55的随机数Q用q个随机C主键从Hashmap中获得对象,取得之后Q把该对象从队列中删除,以免重复取得。由于java中的随机数是Ҏ旉生成的,所以有可能D用户得到的牌不够散,每个用户都摸C条龙岂不是笑话?所以在生成随机数的时候我们加入了一个大素数来作q算Q?/span>

long cardId=new Long((Math.round(Math.random() * 87) % 55)).intValue();通过修改q个大素敎ͼ可以控制某个用户的牌比较好?/span>

五?span style="font: 7pt 'Times New Roman'">             U程

实际上本pȝq没有复杂的U程理Q但是我x供一个控制台让管理员可以理游戏ȝE,可以让它停止、中Dc恢复、重启动Q本来的设计是管理员通过与线EA打交道,通过Aȝ理主U程BQ但是熟悉javaU程的朋友都知道Q线E互相管理基本上是不实际的QD个最单的例子QA如何销毁BQ也怽会说调用B的destroy()Ҏ好了,|上很多讲解javaU程的资料也实是这么说的,但是他们都是鬼扯的,自己ȝ看java源代码吧QThread.destroy()Ҏ的实际代码如下:

public void destroy()

{

    throw new NoSuchMethodError();

}

事实真相是,Thread.destroy()Ҏ自始至终没有被实现q。所有写文章Q教别h用这个方法销毁线E的人,都去撞墙吧,丢h丢大了。最好的办法是A负责生成一个Bq且启动它,然后B自己理生存周期QA和B通过使用可共享的Ҏ来通信Q这是sun推荐的做法?/span>

六?span style="font: 7pt 'Times New Roman'">             异步消息

用户玩牌的过E中Q有很多东西需要记录下来,比如记录用户的积分、等U变化,记录玩牌日志供数据统计等Q当用户数量很多的时候,在数据库中记录这些信息会很耗费资源Q用L了一局之后会可能会{待很长旉。解册个问题的Ҏ是利?a target="_blank">J2EE的消息bean来提供异步通信的机Ӟ需要记录数据的时候,pȝ会封装一个值对象,发送给J2EE容器Q这个操作是很快的,完成之后p回,用户可以l箋操作Q不用关心消息何时被处理。J2EE的消息框架具备如下特征:

◇消息一定会被阅读,而且只阅Mơ。JMS框架有自q法Q把消息~冲?a target="_blank">盘Q就J2EE服务器死掉,消息也不会丢失?/span>

◇系l采用点对点的Queue消息队列Q可以保证同{优先的消息先q先出?/span>

在Jboss 4.0中,部v消息Bean和Queue队列Q都比weblogic 8.1来的ҎQ只需要在jboss.XML中声明消息目的地Q如果jboss发现该目的地不存在的话,会自动徏立一个,实在很简单。关于消息bean的开发与部vQ我有专门的文章描述?/span>

七?span style="font: 7pt 'Times New Roman'">             启动与退?/span>

Z让系l具备让人满意的性能Q应该尽量多的重用对象,减少创徏新对象。比如上面提到的消息发送,我们的操作是提供一个静态类Q在pȝ启动的时候就初始化,保持与JMS服务器的q接Q系l发送消息的时候,不用再去查询JNDI和生成QueueConnectionFactoryQ这样可以提高系l响应速度?/span>

在数据库q接池的问题上,我们也采用同L操作Q启动的时候初始化N个连接。但是如果在关闭q程的时候不做Q何操作,会导致JMS抛出socket异常Q虽然没什么大的媄响,但L得不专业Q而且池中的连接不被释攄话,也可能导致问题。最好能够让pȝ像jboss{控制台E序一Pctrl+c之后能够执行操作Q释放资源再退出。我们可以通过l进E?U程加上一个Hook来实玎ͼWindowsE序员应该对q个非常熟悉?/span>

Hook应该是一个线E方法,如下Q?/span>

public class Hook extends Thread

{

    public void run()

    {

        //释放数据库连接,销毁连接池

        //关闭与JMS的连?/span>

    }

}

在主U程中加入:Runtime.getRuntime().addShutdownHook(new Hook()) ;那么q程/U程会在退出的时候执行Hook的runҎQ清理资源?/span>



冰河快狼 2008-11-08 23:14 发表评论
]]>
java.util.concurrent 多线E框?/title><link>http://www.aygfsteel.com/jelver/articles/238159.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sun, 02 Nov 2008 04:00:00 GMT</pubDate><guid>http://www.aygfsteel.com/jelver/articles/238159.html</guid><wfw:comment>http://www.aygfsteel.com/jelver/comments/238159.html</wfw:comment><comments>http://www.aygfsteel.com/jelver/articles/238159.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/jelver/comments/commentRss/238159.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/jelver/services/trackbacks/238159.html</trackback:ping><description><![CDATA[     摘要: 原文Qhttp://www.ismayday.com/?p=170 最q由于工作需要,回去好好复习了一遍javaQ学习和温习了和多线E,正则表达式,模式设计QSocket~程{相关的知识Q基本算把某个相当牛的程序看懂了Q从中收获颇深,q期也会把相关的知识点做成笔记放到博客来。当然在q里得好好感谢一下晟晟和刁,在我qh的时候问他们总能扑ֈ自己惌的答案,当然q有晟晟的书Q《精通正则表辑ּ》,看完?..  <a href='http://www.aygfsteel.com/jelver/articles/238159.html'>阅读全文</a><img src ="http://www.aygfsteel.com/jelver/aggbug/238159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/jelver/" target="_blank">冰河快狼</a> 2008-11-02 12:00 <a href="http://www.aygfsteel.com/jelver/articles/238159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank">ȫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ԫ</a>| <a href="http://" target="_blank">Ӣ</a>| <a href="http://" target="_blank">ߴ</a>| <a href="http://" target="_blank">㰲</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ǧ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʱ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ҷ</a>| <a href="http://" target="_blank">ʯ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">³ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">׺</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ګ</a>| <a href="http://" target="_blank">½</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">żҴ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>