随笔-109  评论-187  文章-25  trackbacks-0
  2006年9月19日
利用免费的英语角把英语练好

北京  也乐英语为了满足广大英语爱好者的需要特推出周末免费英语角服务,

北京英语角的组织形式如下:

    1:由也乐英语派出一名外教和一名助理负责组织英语角的活动。

    2: 英语角每周组织一次活动,也乐英语培训学校提供一间教室为大家的活动场所。

    3:英语爱好者可以免费参加英语角的活动,不收取任何费用,此活动是公益活动,也乐英

语不收取任何费用,也不限制参加次数。

    4:也乐英语免费提供给英语爱好者茶水、咖啡、以及活动所采用的书籍报纸。

    5:每周一到2个话题,由外教提前一周告诉大家,大家可以简单准备,以便在课堂上
        跟外教以及同学交流。
   
    6:外教会纠正大家的发音、语法、词汇上的错误,会形成一些总结,也希望大家能够畅所

欲言,大胆的说英语。

     7:所有参加英语角的爱好者,请您在交流期间把手机调为静音。

     也乐英语地址:北京丰台区马家堡西路15号 时代风帆大厦2区1901
     交通状况:地铁四号线角门西站A口上楼即可。 51、501、54、529、698、646、707 嘉园

二里东门下车
     联系电话:010-58423871  15330275871

      此活动由于报名数量众多,所以需要大家提前预约。
      也乐英语网站:www.yellenglish.com
      也乐英语 争做北京最好的英语角.
posted @ 2011-06-19 09:35 小小程序程序员混口饭吃 阅读(2116) | 评论 (0)编辑 收藏
我认为最大的冲击莫过于 惠普,oracle跟惠普的直接竞争会加大,从合作变为竞争,我认为惠普如果不收购redhat来对抗,未来肯定落下风!
posted @ 2009-04-22 09:56 小小程序程序员混口饭吃 阅读(631) | 评论 (0)编辑 收藏
     摘要: 上篇文章讲述了jacorb 的配置,本章讲叙其应用,随后的几篇文章会重点讲述corba的开发   JACORB开发以及corba的请求方式:    JacORB的应用开发一般分为以下五步: 1.写IDL接口定义 2.编译IDL接口定义生成Java类 3.实现步骤2中生成的接口 4.写服务器启动类,并注册到ORB 5.写客户端去获取服务对象引用 &nb...  阅读全文
posted @ 2007-11-22 10:41 小小程序程序员混口饭吃 阅读(8283) | 评论 (2)编辑 收藏

                   how to setup jacorb dev env
1:download JacORB_2_2

       http://www.jacorb.org/download.html
  download ant
       http://ant.apache.org/bindownload.cgi

2:extact JacORB_2_2.jar to d:\JacORB_2_2

3:setup sys environment

       set ANT_HOME=
       set JAVA_HOME=
       set JACORB_HOME=d:\JacORB_2_2
       set PATH=%PATH%;%ANT_HOME%\bin;%JAVA_HOME%\bin;%JACORB_HOME%\bin;
       set CLASSPAHT=.;%CLASSPAHT%;%ANT_HOME%\lib\ant.jar;%JACORB_HOME%\lib\jarorb.jar;%JACORB_HOME%\lib\idl.jar\;%JACORB_HOME%\lib\logkit-1.2.jar

4:rename %JACORB_HOME%\etc\jacorb_properties.template to %JACORB_HOME%\etc\jacorb.properties
  and modify the 50th line to 53th line to
 
       #ORBInitRef.NameService=file:/y:/nsiona.ref
      
ORBInitRef.NameService=file://d://test//NS_Ref
      
#ORBInitRef.NameService=http://www.x.y.z/~user/NS_Ref
      
#ORBInitRef.TradingService=http://www.x.y.z/~user/TraderRef
 
  modify 618th line to
       jacorb.naming.ior_filename=d://test//NS_Ref

5:rename  %JACORB_HOME%\jacotemplate.bat to %JACORB_HOME%\jaco.bat
 
  and modify related env variable
 
  rename   %JACORB_HOME%\idltemplate.bat to %JACORB_HOME%\idl.bat
  
  and modify related env variable

 

6:  use ant compile and build idl and java


     cd  %JACORB_HOME%\demo\grid  

     run ant
   
     the generate class file in %JACORB_HOME%\classes  and generated java file in %JACORB_HOME%\demo\grid


7: open a new cmd window:
          cd %JACORB_HOME%   ns
 
   you can see the following result:   
       [ configuration jacorb loaded from file %JAORB_HOME%\etc\jacorb.properties]

   open a new cmd window:
          cd %JACORB_HOME%   jaco demo.grid.Server
  you can see the following result:   
  [ configuration jacorb loaded from file %JAORB_HOME%\etc\jacorb.properties]
  
  open a new cmd window:
          cd %JACORB_HOME%   jaco demo.grid.client
    you can see the following result:   
 
  [ configuration jacorb loaded from file D:\work\nj\JACORB\etc\jacorb.properties]
   Height = 31
   Width = 14
   Old value at (30,13): 0.21
   Setting (30,13) to 470.11
   New value at (30,13): 470.11
   MyException, reason: This is only a test exception, no harm done :-)
   done.

posted @ 2007-11-21 10:36 小小程序程序员混口饭吃 阅读(4230) | 评论 (4)编辑 收藏
 
oracle的分析函数over 及开窗函数
一:分析函数over
Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是
对于每个组返回多行,而聚合函数对于每个组只返回一行。
下面通过几个例子来说明其应用。                                       
1:统计某商店的营业额。        
     date       sale
     1           20
     2           15
     3           14
     4           18
     5           30
    规则:按天统计:每天都统计前面几天的总额
    得到的结果:
    DATE   SALE       SUM
    ----- -------- ------
    1      20        20           --1天           
    2      15        35           --1天+2天           
    3      14        49           --1天+2天+3天           
    4      18        67            .          
    5      30        97            .
     
2:统计各班成绩第一名的同学信息
    NAME   CLASS S                         
    ----- ----- ----------------------
    fda    1      80                     
    ffd    1      78                     
    dss    1      95                     
    cfe    2      74                     
    gds    2      92                     
    gf     3      99                     
    ddd    3      99                     
    adf    3      45                     
    asdf   3      55                     
    3dd    3      78              
   
    通过:   
    --
    select * from                                                                       
    (                                                                            
    select name,class,s,rank()over(partition by class order by s desc) mm from t2
    )                                                                            
    where mm=1
    --
    得到结果:
    NAME   CLASS S                       MM                                                                                        
    ----- ----- ---------------------- ----------------------
    dss    1      95                      1                      
    gds    2      92                      1                      
    gf     3      99                      1                      
    ddd    3      99                      1          
   
    注意:
    1.在求第一名成绩的时候,不能用row_number(),因为如果同班有两个并列第一,row_number()只返回一个结果          
    2.rank()和dense_rank()的区别是:
      --rank()是跳跃排序,有两个第二名时接下来就是第四名
      --dense_rank()l是连续排序,有两个第二名时仍然跟着第三名
     
     
3.分类统计 (并显示信息)
    A   B   C                      
    -- -- ----------------------
    m   a   2                      
    n   a   3                      
    m   a   2                      
    n   b   2                      
    n   b   1                      
    x   b   3                      
    x   b   2                      
    x   b   4                      
    h   b   3
   select a,c,sum(c)over(partition by a) from t2                
   得到结果:
   A   B   C        SUM(C)OVER(PARTITIONBYA)      
   -- -- ------- ------------------------
   h   b   3        3                        
   m   a   2        4                        
   m   a   2        4                        
   n   a   3        6                        
   n   b   2        6                        
   n   b   1        6                        
   x   b   3        9                        
   x   b   2        9                        
   x   b   4        9                        
  
   如果用sum,group by 则只能得到
   A   SUM(C)                            
   -- ----------------------
   h   3                      
   m   4                      
   n   6                      
   x   9                      
   无法得到B列值       
  
=====

select * from test

数据:
A B C
1 1 1
1 2 2
1 3 3
2 2 5
3 4 6


---将B栏位值相同的对应的C 栏位值加总
select a,b,c, SUM(C) OVER (PARTITION BY B) C_Sum
from test

A B C C_SUM
1 1 1 1
1 2 2 7
2 2 5 7
1 3 3 3
3 4 6 6



---如果不需要已某个栏位的值分割,那就要用 null

eg: 就是将C的栏位值summary 放在每行后面

select a,b,c, SUM(C) OVER (PARTITION BY null) C_Sum
from test

A B C C_SUM
1 1 1 17
1 2 2 17
1 3 3 17
2 2 5 17
3 4 6 17

 

求个人工资占部门工资的百分比

SQL> select * from salary;

NAME DEPT SAL
---------- ---- -----
a 10 2000
b 10 3000
c 10 5000
d 20 4000

SQL> select name,dept,sal,sal*100/sum(sal) over(partition by dept) percent from salary;

NAME DEPT SAL PERCENT
---------- ---- ----- ----------
a 10 2000 20
b 10 3000 30
c 10 5000 50
d 20 4000 100

二:开窗函数           
      开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:
1:     
   over(order by salary) 按照salary排序进行累计,order by是个默认的开窗函数
   over(partition by deptno)按照部门分区
2:
  over(order by salary range between 5 preceding and 5 following)
   每行对应的数据窗口是之前行幅度值不超过5,之后行幅度值不超过5
   例如:对于以下列
     aa
     1
     2
     2
     2
     3
     4
     5
     6
     7
     9
   
   sum(aa)over(order by aa range between 2 preceding and 2 following)
   得出的结果是
            AA                       SUM
            ---------------------- -------------------------------------------------------
            1                       10                                                      
            2                       14                                                      
            2                       14                                                      
            2                       14                                                      
            3                       18                                                      
            4                       18                                                      
            5                       22                                                      
            6                       18                                                                
            7                       22                                                                
            9                       9                                                                 
             
   就是说,对于aa=5的一行 ,sum为   5-1<=aa<=5+2 的和
   对于aa=2来说 ,sum=1+2+2+2+3+4=14     ;
   又如 对于aa=9 ,9-1<=aa<=9+2 只有9一个数,所以sum=9    ;
              
3:其它:
     over(order by salary rows between 2 preceding and 4 following)
          每行对应的数据窗口是之前2行,之后4行
4:下面三条语句等效:           
     over(order by salary rows between unbounded preceding and unbounded following)
          每行对应的数据窗口是从第一行到最后一行,等效:
     over(order by salary range between unbounded preceding and unbounded following)
           等效
     over(partition by null)
posted @ 2007-11-13 13:33 小小程序程序员混口饭吃 阅读(50023) | 评论 (13)编辑 收藏

由于一些原因,最近要复习一些东西,所以就把JMS的东西再复习一遍,以下便是例子

jms 中最重要的几个概念destination,ACKNOWLEDGE,subscribe,durable subscribe

destination:topic queque
  queue简单点说就是1:1 一个消息只能由一个consumer去消费,别的consumer来消费的时候已经没了,先到先得
topic简单点说就是1:N 一个消息可以由多个consumer来消费,谁来消费都有
 subscribe,拿topic来说如果当前订阅不是持久订阅,只有再订阅后生产者生产得消息才能被consumer得到,持久订阅只要没有被consumer消费,早晚会消费这个消息
 
 
 
 一下是几个例子
 
 queuesend:queque消息产生
 queuereceive:queque消息得消费
 topicsend :topic消息得产生
 topicreceive1:topic消息的非订阅
 topicrecieve2:topic消息的持久订阅
 
 这个例子实在WEBLOGIC814上测试过的,当然要定义JMSSERVER,FACTORY,DESTINATION。
 
 
 
 QueueSend
 
 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class QueueSend {
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

 // Defines the JNDI provider url.
 public final static String PROVIDER_URL = " t3://localhost:7001";

 // Defines the JMS connection factory for the queue.
 public final static String JMS_FACTORY = "SendJMSFactory";

 // Defines the queue.
 public final static String QUEUE = "SendJMSQueue";

 private QueueConnectionFactory qconFactory;

 private QueueConnection qcon;

 private QueueSession qsession;

 private QueueSender qsender;

 private Queue queue;

 private TextMessage msg;

 /**
  * Creates all the necessary objects for sending messages to a JMS queue.
  *
  * @param ctx
  *            JNDI initial context
  * @param queueName
  *            name of queue
  * @exception NamingException
  *                if operation cannot be performed
  * @exception JMSException
  *                if JMS fails to initialize due to internal error
  */
 public void init(Context ctx, String queueName) throws NamingException,
   JMSException {
  qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
  qcon = qconFactory.createQueueConnection();
  qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
  queue = (Queue) ctx.lookup(queueName);
  qsender = qsession.createSender(queue);
  msg = qsession.createTextMessage();
  qcon.start();
 }

 /**
  * Sends a message to a JMS queue.
  *
  * @param message
  *            message to be sent
  * @exception JMSException
  *                if JMS fails to send message due to internal error
  */
 public void send(String message) throws JMSException {
  msg.setText(message);
  qsender.send(msg);
 }

 /**
  * Closes JMS objects.
  *
  * @exception JMSException
  *                if JMS fails to close objects due to internal error
  */
 public void close() throws JMSException {
  qsender.close();
  qsession.close();
  qcon.close();
 }

 /**
  * main() method.
  *
  * @param args
  *            WebLogic Server URL
  * @exception Exception
  *                if operation fails
  */
 public static void main(String[] args) throws Exception {
  try {
   InitialContext ic = getInitialContext();
   QueueSend qs = new QueueSend();
   qs.init(ic, QUEUE);
   readAndSend(qs);
   qs.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 private static void readAndSend(QueueSend qs) throws IOException,
   JMSException {
  BufferedReader msgStream = new BufferedReader(new InputStreamReader(
    System.in));
  String line = null;
  boolean quitNow = false;
  do {
   System.out.print("Enter message (\"quit\" to quit): ");
   line = msgStream.readLine();
   if (line != null && line.trim().length() != 0) {
    qs.send(line);
    System.out.println("JMS Message Sent: " + line + "\n");
    quitNow = line.equalsIgnoreCase("quit");
   }
  } while (!quitNow);

 }

 private static InitialContext getInitialContext() throws NamingException {
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
  env.put(Context.PROVIDER_URL, PROVIDER_URL);
  return new InitialContext(env);
 }

}


QueueReceive

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class QueueReceive implements MessageListener {
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

 // Defines the JNDI provider url.
 public final static String PROVIDER_URL = " t3://localhost:7001";

 // Defines the JMS connection factory for the queue.
 public final static String JMS_FACTORY = "SendJMSFactory";

 // Defines the queue.
 public final static String QUEUE = "SendJMSQueue";

 private QueueConnectionFactory qconFactory;

 private QueueConnection qcon;

 private QueueSession qsession;

 private QueueReceiver qreceiver;

 private Queue queue;

 private boolean quit = false;

 /**
  * Message listener interface.
  *
  * @param msg
  *            message
  */
 public void onMessage(Message msg) {
  try {
   String msgText;
   if (msg instanceof TextMessage) {
    msgText = ((TextMessage) msg).getText();
   } else {
    msgText = msg.toString();
   }

   System.out.println("Message Received: " + msgText);

//   if (msgText.equalsIgnoreCase("123")) {
//    synchronized (this) {
//     quit = true;
//     this.notifyAll(); // Notify main thread to quit
//    }
//   }
  } catch (JMSException jmse) {
   jmse.printStackTrace();
  }
 }

 /**
  * Creates all the necessary objects for receiving messages from a JMS
  * queue.
  *
  * @param ctx
  *            JNDI initial context
  * @param queueName
  *            name of queue
  * @exception NamingException
  *                if operation cannot be performed
  * @exception JMSException
  *                if JMS fails to initialize due to internal error
  */
 public void init(Context ctx, String queueName) throws NamingException,
   JMSException {
  qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
  qcon = qconFactory.createQueueConnection();
  qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
  queue = (Queue) ctx.lookup(queueName);
  qreceiver = qsession.createReceiver(queue);
  qreceiver.setMessageListener(this);
  qcon.start();
 }

 /**
  * Closes JMS objects.
  *
  * @exception JMSException
  *                if JMS fails to close objects due to internal error
  */
 public void close() throws JMSException {
  qreceiver.close();
  qsession.close();
  qcon.close();
 }

 /**
  * main() method.
  *
  * @param args
  *            WebLogic Server URL
  * @exception Exception
  *                if execution fails
  */

 public static void main(String[] args) throws Exception {

  InitialContext ic = getInitialContext();
  QueueReceive qr = new QueueReceive();
  qr.init(ic, QUEUE);

  System.out
    .println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");

  // Wait until a "quit" message has been received.
  synchronized (qr) {
   System.out.println("111111111111");
   while (!qr.quit) {
    try {
     System.out.println("2222222222");
     qr.wait();
     System.out.println("333333333");
    } catch (InterruptedException ie) {
    }
   }
  }
  qr.close();
 }

 private static InitialContext getInitialContext() throws NamingException {
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
  env.put(Context.PROVIDER_URL, PROVIDER_URL);
  return new InitialContext(env);
 }

}

 

TopicSend

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.jms.TopicPublisher;
public class TopicSend {
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

 // Defines the JNDI provider url.
 public final static String PROVIDER_URL = " t3://localhost:7001";

 // Defines the JMS connection factory for the queue.
 public final static String JMS_FACTORY = "SendJMSFactory";

 // Defines the queue.
 public final static String TOPIC = "SendJMSTopic";

 private TopicConnectionFactory tconFactory;

 private TopicConnection tcon;

 private TopicSession tsession;

 private TopicPublisher tsender;

 private Topic topic;

 private TextMessage msg;
 public static InitialContext ic ;

 /**
  * Creates all the necessary objects for sending messages to a JMS queue.
  *
  * @param ctx
  *            JNDI initial context
  * @param queueName
  *            name of queue
  * @exception NamingException
  *                if operation cannot be performed
  * @exception JMSException
  *                if JMS fails to initialize due to internal error
  */
 public void init(Context ctx, String queueName) throws NamingException,
   JMSException {
  tconFactory = (TopicConnectionFactory) ctx.lookup(JMS_FACTORY);
  tcon = tconFactory.createTopicConnection();
  tsession = tcon.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
  System.out.println(topic);
  topic = (Topic) ctx.lookup(queueName);
  System.out.println(topic);
  tsender = tsession.createPublisher(topic);
  msg = tsession.createTextMessage();
  tcon.start();
 }

 /**
  * Sends a message to a JMS queue.
  *
  * @param message
  *            message to be sent
  * @exception JMSException
  *                if JMS fails to send message due to internal error
  */
 public void send(String message) throws JMSException ,NamingException{
  System.out.println(topic+"-----------");
  msg.setText(message);
  tsender.publish(msg);
 }

 /**
  * Closes JMS objects.
  *
  * @exception JMSException
  *                if JMS fails to close objects due to internal error
  */
 public void close() throws JMSException {
  tsender.close();
  tsession.close();
  tcon.close();
 }

 /**
  * main() method.
  *
  * @param args
  *            WebLogic Server URL
  * @exception Exception
  *                if operation fails
  */
 public static void main(String[] args) throws Exception {
  try {
   ic= getInitialContext();
   TopicSend ts = new TopicSend();
   ts.init(ic, TOPIC);
   readAndSend(ts);
   ts.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 private static void readAndSend(TopicSend ts) throws IOException,
   JMSException,NamingException {
  BufferedReader msgStream = new BufferedReader(new InputStreamReader(
    System.in));
  String line = null;
  boolean quitNow = false;
  do {
   System.out.print("Enter message (\"quit\" to quit): ");
   line = msgStream.readLine();
   if (line != null && line.trim().length() != 0) {
    ts.send(line);
   
    System.out.println("JMS Message Sent: " + line + "\n");
    quitNow = line.equalsIgnoreCase("quit");
   }
  } while (!quitNow);

 }

 private static InitialContext getInitialContext() throws NamingException {
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
  env.put(Context.PROVIDER_URL, PROVIDER_URL);
  return new InitialContext(env);
 }

}

 

TopicReceive1

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class TopicReceive1 implements MessageListener {
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

 // Defines the JNDI provider url.
 public final static String PROVIDER_URL = " t3://localhost:7001";

 // Defines the JMS connection factory for the queue.
 public final static String JMS_FACTORY = "SendJMSFactory";

 // Defines the queue.
 public final static String TOPIC = "SendJMSTopic";

 private TopicConnectionFactory tconFactory;

 private TopicConnection tcon;

 private TopicSession tsession;

 private TopicSubscriber tsubscriber;

 private Topic topic;

 private boolean quit = false;

 /**
  * Message listener interface.
  *
  * @param msg
  *            message
  */
 public void onMessage(Message msg) {
  System.out.println("===================");
  try {
   String msgText;
   if (msg instanceof TextMessage) {
    msgText = ((TextMessage) msg).getText();
   } else {
    msgText = msg.toString();
   }

   System.out.println("Message Received: " + msgText);

//   if (msgText.equalsIgnoreCase("123")) {
//    synchronized (this) {
//     quit = true;
//     this.notifyAll(); // Notify main thread to quit
//    }
//   }
  } catch (JMSException jmse) {
   jmse.printStackTrace();
  }
 }

 /**
  * Creates all the necessary objects for receiving messages from a JMS
  * queue.
  *
  * @param ctx
  *            JNDI initial context
  * @param queueName
  *            name of queue
  * @exception NamingException
  *                if operation cannot be performed
  * @exception JMSException
  *                if JMS fails to initialize due to internal error
  */
 public void init(Context ctx, String queueName) throws NamingException,
   JMSException {
  tconFactory = (TopicConnectionFactory) ctx.lookup(JMS_FACTORY);
  tcon = tconFactory.createTopicConnection();
  tsession = tcon.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
  topic = (Topic) ctx.lookup(queueName);
  tsubscriber = tsession.createSubscriber(topic);
  //System.out.println("12");
  //Message msg = treceiver.receive();
  //msg.acknowledge();
  //tsubscriber = tsession.createSubscriber(topic);Message msg = tsubscriber.receive();msg.acknowledge();
  //System.out.println(msg);
  tsubscriber.setMessageListener(this);
  tcon.start();
 }

 /**
  * Closes JMS objects.
  *
  * @exception JMSException
  *                if JMS fails to close objects due to internal error
  */
 public void close() throws JMSException {
  tsubscriber.close();
  tsession.close();
  tcon.close();
 }

 /**
  * main() method.
  *
  * @param args
  *            WebLogic Server URL
  * @exception Exception
  *                if execution fails
  */

 public static void main(String[] args) throws Exception {

  InitialContext ic = getInitialContext();
  TopicReceive1 tr1 = new TopicReceive1();
  tr1.init(ic, TOPIC);

  System.out
    .println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");
  
  

  // Wait until a "quit" message has been received.
//  synchronized (tr1) {
//   System.out.println("111111111111");
//   while (!tr1.quit) {
//    try {
//     System.out.println("2222222222");
//     tr1.wait();
//     System.out.println("333333333");
//    } catch (InterruptedException ie) {
//    }
//   }
//  }
  tr1.close();
 }

 private static InitialContext getInitialContext() throws NamingException {
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
  env.put(Context.PROVIDER_URL, PROVIDER_URL);
  return new InitialContext(env);
 }

}


TopicReceive2


import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class TopicReceive2 {
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

 // Defines the JNDI provider url.
 public final static String PROVIDER_URL = " t3://localhost:7001";

 // Defines the JMS connection factory for the queue.
 public final static String JMS_FACTORY = "SendJMSFactory";

 // Defines the queue.
 public final static String TOPIC = "SendJMSTopic";

 private TopicConnectionFactory tconFactory;

 private TopicConnection tcon;

 private TopicSession tsession;

 private TopicSubscriber tsubscriber;

 private Topic topic;

 private boolean quit = false;


 /**
  * Creates all the necessary objects for receiving messages from a JMS
  * queue.
  *
  * @param ctx
  *            JNDI initial context
  * @param queueName
  *            name of queue
  * @exception NamingException
  *                if operation cannot be performed
  * @exception JMSException
  *                if JMS fails to initialize due to internal error
  */
 public void init(Context ctx, String queueName) throws NamingException,
   JMSException,InterruptedException {
  tconFactory = (TopicConnectionFactory) ctx.lookup(JMS_FACTORY);
  tcon = tconFactory.createTopicConnection();
  tcon.setClientID("IP10.200.7.104");
  tcon.start();
  
  tsession = tcon.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
  System.out.println("333333333333");
  topic = (Topic) ctx.lookup(queueName);
  //tsubscriber = tsession.createSubscriber(topic);
  tsubscriber= tsession.createDurableSubscriber(topic,"88888");
   for (int i=0; i<3; i++) {
             //
             TextMessage message = (TextMessage) tsubscriber.receive();
             System.out.println("message["+i+"]: " + message.getText());
         }
          Thread.sleep(10000);
  //System.out.println("12");
  //Message msg = treceiver.receive();
  //msg.acknowledge();
  //tsubscriber = tsession.createSubscriber(topic);Message msg = tsubscriber.receive();msg.acknowledge();
  //System.out.println(msg);

 }

 /**
  * Closes JMS objects.
  *
  * @exception JMSException
  *                if JMS fails to close objects due to internal error
  */
 public void close() throws JMSException {
  tsubscriber.close();
  tsession.close();
  tcon.close();
 }

 /**
  * main() method.
  *
  * @param args
  *            WebLogic Server URL
  * @exception Exception
  *                if execution fails
  */

 public static void main(String[] args) throws Exception {

  InitialContext ic = getInitialContext();
  TopicReceive2 tr2 = new TopicReceive2();
  tr2.init(ic, TOPIC);

  System.out
    .println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");
  
  

  // Wait until a "quit" message has been received.
//  synchronized (tr1) {
//   System.out.println("111111111111");
//   while (!tr1.quit) {
//    try {
//     System.out.println("2222222222");
//     tr1.wait();
//     System.out.println("333333333");
//    } catch (InterruptedException ie) {
//    }
//   }
//  }
  tr2.close();
 }

 private static InitialContext getInitialContext() throws NamingException {
  Hashtable env = new Hashtable();
  env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
  env.put(Context.PROVIDER_URL, PROVIDER_URL);
  return new InitialContext(env);
 }

}

posted @ 2007-08-15 09:20 小小程序程序员混口饭吃 阅读(1161) | 评论 (0)编辑 收藏

一、rpm包安装方式步骤:
引用:

1、找到相应的软件包,比如soft.version.rpm,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.version.rpm所在的目录;

4、输入rpm -ivh soft.version.rpm




二、deb包安装方式步骤:

引用:
1、找到相应的软件包,比如soft.version.deb,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.version.deb所在的目录;

4、输入dpkg -i soft.version.deb




三、tar.gz源代码包安装方式:

引用:
1、找到相应的软件包,比如soft.tar.gz,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.tar.gz所在的目录;

4、tar -xzvf soft.tar.gz //一般会生成一个soft目录

5、cd soft

6、./configure

7、make

8、make install




四、tar.bz2源代码包安装方式:

引用:
1、找到相应的软件包,比如soft.tar.bz2,下载到本机某个目录;

2、打开一个终端,su -成root用户;

3、cd soft.tar.bz2所在的目录;

4、tar -xjvf soft.tar.bz2 //一般会生成一个soft目录

5、cd soft

6、./configure

7、make

8、make install




五、apt方式安装:

引用:
1、打开一个终端,su -成root用户;

2、apt-cache search soft 注:soft是你要找的软件的名称或相关信息

3、如果2中找到了软件soft.version,则用apt-get install soft.version命令安装软件 注:只要你可以上网,只需要用apt-cache search查找软件,用apt-get install软件




六、bin文件安装:

如果你下载到的软件名是soft.bin,一般情况下是个可执行文件,安装方法如下:

引用:
1、打开一个终端,su -成root用户;

2、chmod +x soft.bin

3、./soft.bin //运行这个命令就可以安装软件了




七、不需要安装的软件:

有了些软件,比如lumaqq,是不需要安装的,自带jre解压缩后可直接运行。假设下载的是lumaqq.tar.gz,使用方法如下:

引用:
1、打开一个终端,su -成root用户;

2、tar -xzvf lumaqq.tar.gz //这一步会生成一个叫LumaQQ的目录

3、cd LumaQQ

4、chmod +x lumaqq //设置lumaqq这个程序文件为可运行

5、此时就可以运行lumaqq了,用命令./lumaqq即可,但每次运行要输入全路径或切换到刚才生成的LumaQQ目录里

6、为了保证不设置路径就可以用,你可以在/bin目录下建立一个lumaqq的链接,用命令ln -s lumaqq /bin/ 即可,以后任何时候打开一个终端输入lumaqq就可以启动QQ聊天软件了

7、如果你要想lumaqq有个菜单项,使用菜单编辑工具,比如Alacarte Menu Editor,找到上面生成的LumaQQ目录里的lumaqq设置一个菜单项就可以了,当然你也可以直接到 /usr/share/applications目录,按照里面其它*.desktop文件的格式生成一个自己的desktop文件即可。

posted @ 2007-08-10 09:39 小小程序程序员混口饭吃 阅读(611) | 评论 (0)编辑 收藏

计划任务工具 cron 的配置和说明

作者:北南南北
来自:LinuxSir.Org
摘要:Linux操作系统中,计划任务通常由cron来承担,了解或掌握cron,能为我们管理服务器带来更多的便利,也能省却更多的时间。本文也举了一些简单明了的例子,为了让新手上路方便;

目录


++++++++++++++++++++++++++++++++++++++
正文
++++++++++++++++++++++++++++++++++++++


1、计划任务概说;

计划任务,是任务在约定的时间执行已经计划好的工作,这是表面的意思。在Linux中,我们经常用到 crond 服务器来完成这项工作。cron服务器可以根据配置文件约定的时间来执行特定的作务。比如我们可以在配置文件中约定每天早上4点,对httpd 服务器重新启动,这就是一个计划任务;

下面我们先来说说cron;


2、cron;

在Linux系统中,计划任务一般是由cron承担,我们可以把cron设置为开机时自动启动。cron启动后,它会读取它的所有配置文件(全局性配置文件/etc/crontab,以及每个用户的计划任务配置文件),然后cron会根据命令和执行时间来按时来调用度工作任务。


2.1 cron 的安装和启动;

在一般情况下,cron都是系统默认安装的,我们要学会查看软件包是否已经安装;


2.1.1 在Redhat 或 Fedora等RPM包管理的系统的安装;

判断系统是否已经安装cron相关的包

Fedora 5.0 系统的情况;

其它版本的Fedora及Redhat的系统和这相似;

[root@localhost ~]# rpm -qa |grep cron
vixie-cron-4.1-54.FC5
anacron-2.3-36.1
crontabs-1.10-7.1

 

其中vixie-cron软件包是cron的主程序,您可以通过下面的命令来了解它,其它软件包同理;

[root@localhost beinan]# rpm -ql vixie-cron

 

crontabs 软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表格的程序。cron 守护进程检查 crontab 文件来查看某个指定命令被调度执行的时间。如果命令已经调度,守护进程就会执行它们。了解crontabs软件包都安装了些什么,应该用下面的命令;

[root@localhost beinan]# rpm -ql crontabs

 

如果没有安装,可以从光盘中找出文件名带有cron字样的软件包来安装。

[root@localhost ~]# rpm -ivh vixie-cron-4.1-54.FC5*
[root@localhost ~]# rpm -ivh crontabs*

 

也可以用yum 来在线安装;

[root@localhost ~]# yum install vixie-cron
[root@localhost ~]# yum install crontabs

 


2.1.2 在Slackware系统中的安装;

在Slackware中cron软件包是 dcron,您可以在光盘中找出来安装它;

查看是否已经安装了dcron软件包,您可以这样查看。在这里能列出软件包详细的安装情况;

[root@localhost ~]# more /var/adm/packages/dcron*

 

如果没有安装,请用下面的命令来安装。在第一张安装盘中找出dcron软件包;

[root@localhost ~]# installpkg dcron*.tgz

 


2.1.3 cron 的开启、停止、重新启动方法;

cron配置文件被修改后,想让新文件生效,必须重新crond服务器,有两种方法可供选择;


第一种 在Fedora或Redhat 等以RPM包管理的系统中;

[root@localhost ~]# /etc/init.d/crond start
[root@localhost ~]# /etc/init.d/crond stop
[root@localhost ~]# /etc/init.d/crond restart

 

如果想在Fedora 和 Redhat 或以这些发行版为基础克隆的发行版,如果想自动开机运行,请用下面的办法;

[root@localhost ~]# chkconfig --levels 35 crond on

 

第二种:通用

[root@localhost ~]# pgrep crond 注:判断crond 是否在运行;
[root@localhost ~]# pkill crond 注:杀掉正在运行中的crond;
[root@localhost ~]# pgrep crond 注:查看是否被杀掉了;
[root@localhost ~]# /usr/sbin/crond 注:运行crond;

 


2.2 cron 配置文件;

cron 是一个服务器程序,我们都知道Linux的服务器的配置,大多是通过配置文件来完成的,cron自然也不例外,在Redhat/Fedora 等系统中它的全局性配置文件是/etc/crontab;在Slackware系统中,全局性文件是/var/spool/cron/crontabs/root 。每个用户也有自己的cron配置文件,我们可以通过crontab -e 来编辑它;


2.2.1 全局性配置文件;

下面是一个全局性的配置文件例子,以Fedora Core 5为例;

[root@localhost ~]# more /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# run-parts
1 * * * * root run-parts /etc/cron.hourly
#
2 4 * * * root run-parts /etc/cron.daily
#
22 4 * * 7 root run-parts /etc/cron.weekly
#
42 4 1 * * root run-parts /etc/cron.monthly
#
0,5,10,15,20,25,30,35,40,45,50,55 * * * * root /usr/bin/mrtg /etc/mrtg/mrtg.cfg

 

对于全局性配置文件,我们要用root权限来更改,一般是通过crontab -e 来修改。但有时也并不一定是这样的,比如Fedora Core 5 如果通过crontab -e 修改的是root用户的cron 配置文件。所以我们要在Fedora Core 5中修改全局性配置文件可以用vi 编辑器来修改。vi的用法请参考:《文件编辑器 vi》

在全局性配置文件中,定义了可执行命令的路径环境变量,所用SHELL类型的定义等,这些大多不用修改;我们经常添加的是计划任务或修改任务执行的时间等;

在全局性配置文件中,我们发现有类似这些行;

1 * * * * root run-parts /etc/cron.hourly 注:表示每个小时的第一分钟,开始执行/etc/hourly目录下的可执行程序或脚本;
2 4 * * * root run-parts /etc/cron.daily 注:表示每天的4点2分,开始执行/etc/cron.daily目录下的可执行程序或脚本;
22 4 * * 7 root run-parts /etc/cron.weekly 注:每年第7个周4点我22分,开始执行 /etc/cron.weekly目录下的可执行程序或脚本;
42 4 1 * * root run-parts /etc/cron.monthly 注:每月第1天的4点42分,开始执行/etc/cron.monthly目录下的可执行程序或脚本;

 

这些行是用来在同一时间批量执行任务的,我们在以后的例子中独立出来解说,在这里只是让大家心中有数;


2.2.2 cron 配置计划任务的书写格式

分钟 小时 日 月 周 [用户名] 命令

 

说明:

第一段应该定义的是:分钟,表示每个小时的第几分钟来执行。范围是从0-59
        第二段应该定义的是:小时,表示从第几个小时来执行,范围是从0-23
        第三段应该定义的是:日期,表示从每个月的第几天执行,范围从1-31
        第四段应该定义的是:月,表示每年的第几个月来执行,范围从1-12
        第五段应该定义的是:周,表示每周的第几天执行,范围从0-6,其中 0表示星期日。
        每六段应该定义的是:用户名,也就是执行程序要通过哪个用户来执行,这个一般可以省略;
        第七段应该定义的是:执行的命令和参数。
        

注:其中用户名可是省略,用户名定义的是程序用哪个用户来执行,比如mysql服务器,我们可以定义成以mysql用户来启动、停止、重新启动,这时要写上用户名;不过对于cron来说意义不是太大,因为每个用户都有自己的cron配置文件。有些程序的启动必须用到root用户,这时我们就可以修改root用户的cron配置文件就行了。在每个用户的配置文件中,不必指定用户名。

我们可以把计划任务写在全局性配置文件中,如果您想把一个计划放入全局性配置文件中,就得改发行版所对应的cron全局配置文件,比如Fedora 5的全局性配置文件是/etc/crontab文件;

每个用户也能定义自己的cron配置文件,用crontab -e 命令来定义;

举一例:让机器在每天8点30分重新启动;

关于时间格式中有7个字段。我们可以直接更改或者添加,当然这是系统任务调用。举个例子,比如我在每天的早上8点30分重新启动机器,就可以在
/etc/crontab中加入下面的两句,第一句就是注释了。以#号开始,后面写一个自己能知道这是什么任务的备注;

# reboot OS
30 8 * * * root /sbin/reboot

 

第一段应该定义的是:分钟,表示每个小时的第几分钟来执行。范围是从0-59
第二段应该定义的是:小时,表示从第几个小时来执行,范围是从0-23
第三段应该定义的是:日期,表示从每个月的第几天执行,范围从1-31
第四段应该定义的是:月,表示每年的第几个月来执行,范围从1-12
第五段应该定义的是:周,表示每周的第几天执行,范围从0-6,其中 0表示星期日。
每六段应该定义的是:用户名,也就是执行程序要通过哪个用户来执行,这个一般可以省略;
第七段应该定义的是:执行的命令和参数。

对比上面的例子就知道,30是不是分钟??8是不是小时?如果有*代表的地方,表示全部,也就是说,每个月,每天,每星期都要执行。root 表示用root用户执行,命令是/sbin/reboot ,也就是说,系统在每天 8点30分重新启动;

我们可以把每天8点30分重新启动的计划任务写入cron全局性配置文件中,也可以定义在root用户自己的cron配置文件中。如果定义在root自己的配置文件,请用root身份来执行 crontab -e 来修改配置文件;crontab -e 进入修改配置文件的过程,其实和vi的用法一样,请参看vi 的用法:《文件编辑器 vi》

让配置文件生效:如果让配置文件生效,还得重新启动cron,切记,既然每个用户下的cron配置文件修改后。也要重新启动cron服务器。

在Fedora 和Redhat中,我们应该用;

[root@localhost ~]# /etc/init.d/crond restart

 

如果让crond 在开机时运行,应该改变其运行级别;

[root@localhost ~]# chkconfig --levels 35 crond on

 

在Slackware中,如果开机自动运行;

查看/etc/rc.d/rc.M文件是否有如的行,如果没有就加上,大多是有的;

# Start crond (Dillon's crond):
if [ -x /usr/sbin/crond ]; then
  /usr/sbin/crond -l10 >>/var/log/cron 2>&1
</cdoe>
<b>
如果想让立即让cron重启生效,也可以用下面的办法;
</b>
<code>
[root@localhost ~]# pgrep crond 注:查看crond服务器是否运行;
2022
[root@localhost ~]# pkill crond 注:杀死crond;
[root@localhost ~]# pgrep crond 注:查看crond是否退出;
[root@localhost ~]# /usr/sbin/crond 注:启动crond;
[root@localhost ~]# pgrep crond 注:查看crond 是否已经运行得起来了;
3883

 


2.2.3 关于同一时间,同时执行多个任务的定义方法;

我们在前面已经说过,在全局性配置文件中,有类似如下的段落;

1 * * * * root run-parts /etc/cron.hourly 注:表示每个小时的第一分钟,开始执行/etc/hourly目录下的可执行程序或脚本;
2 4 * * * root run-parts /etc/cron.daily 注:表示每天的4点2分,开始执行/etc/cron.daily目录下的可执行程序或脚本;
22 4 * * 7 root run-parts /etc/cron.weekly 注:每年第7个周4点我22分,开始执行 /etc/cron.weekly目录下的可执行程序或脚本;
42 4 1 * * root run-parts /etc/cron.monthly 注:每月第1天的4点42分,开始执行/etc/cron.monthly目录下的可执行程序或脚本;

 

举例来说,我想在每天5点10分来重新启动httpd 服务器,与此同时,我们也可以同时下载一个ISO文件。如果我们按书写计划任务的规则一条一条的来书写,并添加到全局是有点麻烦。不如写一个脚本放在/etc/crond.daily目录中。然后把其权限设置为755 (关于权限的设置,请参考:《Linux 文件和目录的属性》)。

当然我们得改一改上面的 带有/etc/cron.daily那行,改为如下;

10 5 * * * root run-parts /etc/cron.daily
</cdoe>
然后我们到/etc/crond.daily目录中创建两个文件,一个是用来重启httpd服务器的,如下;
<code>
[root@localhost cron.daily]# touch httpd.sh
[root@localhost cron.daily]# chmod 755 httpd.sh
[root@localhost cron.daily]# echo "/etc/init.d/httpd restart" > httpd.sh
[root@localhost cron.daily]# more httpd.sh
/etc/init.d/httpd restart

 

如果我想在每天5点20分下载FC5的镜像,可以再创建一个文件fc5down.sh

[root@localhost cron.daily]# touch fc5down.sh
[root@localhost cron.daily]# chmod 755 fc5down.sh
[root@localhost cron.daily]# echo "/usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso" > fc5down.sh
[root@localhost cron.daily]# more fc5down.sh
/usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso

 

然后我们重新启动一下crond就行了;

[root@localhost cron.daily]# pkill crond
[root@localhost cron.daily]# prep crond
[root@localhost cron.daily]# crond&

 

注意:我只是想说明一下,在同一时间 执行多个计划任务的简单用法,并不是有意教给您每天早上都下载FC5的映像。我举这个例子是为了初学者了解这个功能。如果您有好多的任务在某一时刻执行,那就自己写脚本文件。放在/etc目录下的cron.hourly 、cron.daily 、cron.weekly 、cron.monthly 目录中。凡是放进这些目录的可执行脚本,都能在约定的时间内准确执行。每个目录有每个目录的用途;


2.2.4 对于用户自身的cron 配置文件的说明;

每个用户都有自己的cron配置文件,通过crontab -e 就可以编辑,一般的情况下,在Fedora和Redhat的发行版,我们编辑好用户的cron配置文件保存退出后,系统会自动就存放于/var/spool/cron/目录中,文件以用户名命名。在Slackware中是位于/var/spool/cron/crontabs/目录中。其它的发行版都差不多,有点类似。自己找找吧;查看用户的计划任务是crontab -l

crontab -e 注:编辑用户的cron配置文件;
crontab -l 注:查看用户的计划任务;

 

比如我用beinan用户来运行crontab -e ;

[beinan@localhost ~]$ id 注:判断所用用户身份;
uid=500(beinan) gid=500(beinan) groups=500(beinan)
[beinan@localhost ~]$ crontab -e 注:编辑用户beinan的计划任务;

 

我们在里面定义一个任务;

40 20 * * * /usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso

 

保存退出后,我们用下面的命令来查看beinan用户的计划任务;

[beinan@localhost ~]$ crontab -l
40 20 * * * /usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso

 

配置好后,我们还要重新启动crond服务器,每个用户cron配置文件的改动都得重新启动crond服务器;前面已经说过了,这里省略;值得注意的是重启crond服务器,需要root权限,您可以用su命令切换到root 用户,然后再来重启crond;


在Fedora或Redhat等以RPM包管理的发行版中;

[beinan@localhost ~]$ su
口令:
[root@localhost beinan]# /etc/init.d/crond restart
停止 crond: [确定]
启动 crond: [确定]

 


也可以先杀死crond,再运行crond命令的办法来启动;

[root@localhost beinan]# pkill crond
[root@localhost beinan]# pgrep crond
[root@localhost beinan]# /usr/sbin/crond
[root@localhost beinan]# pgrep crond
6664

 


3、计划任务的应用范围;

计划任务主要是让系统自动完成一些工作。比如我们可以让系统自动在某一时刻清理或备份httpd服务器的日志,然后重新启动httpd服务器,这对网络管理员来说是很重要的。也可以让系统自动清空位于/tmp目录的垃圾文件。

另外值得一提的是,LinuxSir.Org 有很多子站,每个子站都有RSS,能让这些站点的RSS相互投递,也是用cron来完成,比如是在早上4点左右开始执行这个任务。这是一个极为耗费资源的过程,如果不是放在在线人少的时候,基本无法完成,所以只能放在早上进行。作为SIR的管理员,不可能每天早上4点起来点鼠标来完成这些事吧。所以最好的办法就是通过cron来自动运行,以在服务器最清闲的时候来完成这项工作;

posted @ 2007-07-24 11:14 小小程序程序员混口饭吃 阅读(929) | 评论 (0)编辑 收藏
分辨率设置高了X起来后花屏,无法通过X界面恢复回去,只能用普通用户进来后,su 到root上来找到XORG.CONF   文件

修改/etc/X11/xorg.conf 

screen里面的设置最大的那个去掉就好了,重启就可以了
posted @ 2007-07-24 09:19 小小程序程序员混口饭吃 阅读(2590) | 评论 (2)编辑 收藏

一、注销,关机,重启

  注销系统的logout命令

  1,Logout 注销是登陆的相对操作,登陆系统后,若要离开系统,用户只要直接下达logout命令即可:

  [root@localhost root]#logout

  Red Hat Linuxrelease 9(Shike)

  Kernel 2.4.20.8 on an i686

  Login: ← 回到登陆的画面

  2,关机或重新启动的shutdown命令

  Shutdown命令可以关闭所有程序,依照用户的需要,重新启动或关机。

  参数说明如下:

   立即关机:-h 参数让系统立即关机。范例如下:

  [root@localhost root]#shutdown –h now ← 要求系统立即关机

   指定关机时间:time参数可指定关机的时间;或设置多久时间后运行shutdown命令,范例如下:

  [root@localhost root]#shutdown now ← 立刻关机

  [root@localhost root]#shutdown +5 ← 5分钟后关机

  [root@localhost root]#shutdown 10:30 ← 在10:30时关机

   关机后自动重启:-r 参数设置关机后重新启动。范例如下:

  [root@localhost root]#shutdown -r now ← 立刻关闭系统并重启

  [root@localhost root]#shutdown -r 23:59 ← 指定在23:59时重启动

  3,重新启动计算机的reboot命令

  顾名思义,reboot命令是用来重新启动系统的。常用的参数如下:

   -f 参数:不依正常的程序运行关机,直接关闭系统并重新启动计算机。

   -I 参数:在在重新启动之前关闭所有网络接口。

  虽然reboot命令有个参数可以使用,但是一般只需要单独运行reboot命令就可以了

posted @ 2007-07-17 13:27 小小程序程序员混口饭吃 阅读(16087) | 评论 (0)编辑 收藏
 

最近测试OMADM1.2的时候,039040两个case是关于TLS SSL的,搞的很迷惑,最近看了一下原来TLS几乎就是SSL,基本上一摸一样而已。

Sun.com上面看到

SSL was developed by Netscape in 1994, and with input from the Internet community, has evolved to become a standard. It is now under the control of the international standards organization, the Internet Engineering Task Force (IETF). The IETF has renamed SSL to Transport Layer Security (TLS), and released the first specification, version 1.0, in January 1999. TLS 1.0 is a modest upgrade to the most recent version of SSL, version 3.0. The differences between SSL 3.0 and TLS 1.0 are minor.

 

所以这2case基本上测试一个就足够了。

另外tls本来就是传输层上的一个协议,所以要是用HTTPS的话,如果你用应用服务器,比如TOMCAT WBLOGIC,他们都支持SSL,根本不需要程序实现任何东西,只要你会使用keytool生成证书就可以了。

 

这块只是牵扯到JSSE,具体可以到http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html#Introduction

Keytool其实再JRE/LIB/SECUTITY下面的包里面,

C:\j2sdk1.4.2_05\jre\lib\security>keytool

keytool 用法:

 

-certreq     [-v] [-alias <alias>] [-sigalg <sigalg>]

             [-file <csr_file>] [-keypass <keypass>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-delete      [-v] -alias <alias>

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-export      [-v] [-rfc] [-alias <alias>] [-file <cert_file>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-genkey      [-v] [-alias <alias>] [-keyalg <keyalg>]

             [-keysize <keysize>] [-sigalg <sigalg>]

             [-dname <dname>] [-validity <valDays>]

             [-keypass <keypass>] [-keystore <keystore>]

             [-storepass <storepass>] [-storetype <storetype>]

             [-provider <provider_class_name>] ...

 

-help

 

-identitydb [-v] [-file <idb_file>] [-keystore <keystore>]

             [-storepass <storepass>] [-storetype <storetype>]

             [-provider <provider_class_name>] ...

 

-import      [-v] [-noprompt] [-trustcacerts] [-alias <alias>]

             [-file <cert_file>] [-keypass <keypass>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-keyclone    [-v] [-alias <alias>] -dest <dest_alias>

             [-keypass <keypass>] [-new <new_keypass>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-keypasswd   [-v] [-alias <alias>]

             [-keypass <old_keypass>] [-new <new_keypass>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-list        [-v | -rfc] [-alias <alias>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

-printcert   [-v] [-file <cert_file>]

 

-selfcert    [-v] [-alias <alias>] [-sigalg <sigalg>]

             [-dname <dname>] [-validity <valDays>]

             [-keypass <keypass>] [-keystore <keystore>]

             [-storepass <storepass>] [-storetype <storetype>]

             [-provider <provider_class_name>] ...

 

-storepasswd [-v] [-new <new_storepass>]

             [-keystore <keystore>] [-storepass <storepass>]

             [-storetype <storetype>] [-provider <provider_class_name>] ...

 

 

1:生成一个

C:\j2sdk1.4.2_05\jre\lib\security>keytool -genkey -alias duke -keyalg RSA   -val

idity 10 -storetype jks -keystore trust1.jks

2:查看你刚才生成的证书

C:\j2sdk1.4.2_05\jre\lib\security>keytool -list -v -keystore trust1.jks

当然要输入密码了。

但是我不太明白服务器需要2个证书1个是custom identity keystore 一个是custom trust keystore为什么2 的输入类型不一样,一个是KeyEntry另外一个是trustedCertEntry,这个流程到底是怎样的?申请证书->导入证书 还是不明白,请指教。

posted @ 2007-07-04 17:43 小小程序程序员混口饭吃 阅读(1975) | 评论 (1)编辑 收藏
     摘要: 最近复习了一下AXIS,写了2个小例子1:  bean  1package test.soap.vo; 2 3import java.io.Serializable; 4 5public class User implements Serializable {&nbs...  阅读全文
posted @ 2007-06-15 15:48 小小程序程序员混口饭吃| 编辑 收藏

Java对象序列化学习笔记- -

                                      

beejoy 原创  来源:java研究组织


目前网络上关于对象序列化的文章不少,但是我发现详细叙述用法和原理的文章太少。本人
把自己经过经验总结和实际运用中的体会写成的学习笔记贡献给大家。希望能为整个java社
区的繁荣做一点事情。
 
序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,
可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接
将对象数据发送到另一主机。对象序列化功能非常简单、强大,在RMI、Socket、JMS、EJB
都有应用。对象序列化问题在网络编程中并不是最激动人心的课题,但却相当重要,具有
许多实用意义。
一:对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机
上的服务,就像在本地机上运行对象时一样。
二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。
可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序
列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能
得到整个对象序列。
 
从上面的叙述中,我们知道了对象序列化是java编程中的必备武器,那么让我们从基础开始
,好好学习一下它的机制和用法。


java序列化比较简单,通常不需要编写保存和恢复对象状态的定制代码。实现java.io.Seri
alizable接口的类对象可以转换成字节流或从字节流恢复,不需要在类中增加任何代码。只
有极少数情况下才需要定制代码保存或恢复对象状态。这里要注意:不是每个类都可序列化,
有些类是不能序列化的,例如涉及线程的类与特定JVM有非常复杂的关系。

序列化机制:

序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字
节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列
化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的
对象实例。ObjectOutputStream中的序列化过程与字节流连接,包括对象类型和版本信息。
反序列化时,JVM用头信息生成对象实例,然后将对象字节流中的数据复制到对象数据成员中。
下面我们分两大部分来阐述:


处理对象流:
(序列化过程和反序列化过程)


java.io包有两个序列化对象的类。ObjectOutputStream负责将对象写入字节流,ObjectInp
utStream从字节流重构对象。
    我们先了解ObjectOutputStream类吧。ObjectOutputStream类扩展DataOutput接口。
writeObject()方法是最重要的方法,用于对象序列化。如果对象包含其他对象的引用,则
writeObject()方法递归序列化这些对象。每个ObjectOutputStream维护序列化的对象引用表,
防止发送同一对象的多个拷贝。(这点很重要)由于writeObject()可以序列化整组交叉引用的
对象,因此同一ObjectOutputStream实例可能不小心被请求序列化同一对象。这时,进行反引用
序列化,而不是再次写入对象字节流。
下面,让我们从例子中来了解ObjectOutputStream这个类吧。

// 序列化 today's date 到一个文件中.
    FileOutputStream f = new FileOutputStream("tmp");
    ObjectOutputStream s = new ObjectOutputStream(f);
    s.writeObject("Today");
    s.writeObject(new Date());
    s.flush();


 
现在,让我们来了解ObjectInputStream这个类。它与ObjectOutputStream相似。它扩展Dat
aInput接口。ObjectInputStream中的方法镜像DataInputStream中读取Java基本数据类型的
公开方法。readObject()方法从字节流中反序列化对象。每次调用readObject()方法都返回
流中下一个Object。对象字节流并不传输类的字节码,而是包括类名及其签名。readObject()
收到对象时,JVM装入头中指定的类。如果找不到这个类,则readObject()抛出
ClassNotFoundException,如果需要传输对象数据和字节码,则可以用RMI框架。
ObjectInputStream的其余方法用于定制反序列化过程。
例子如下:

//从文件中反序列化 string 对象和 date 对象
    FileInputStream in = new FileInputStream("tmp");
    ObjectInputStream s = new ObjectInputStream(in);
    String today = (String)s.readObject();
    Date date = (Date)s.readObject();

 

定制序列化过程:


序列化通常可以自动完成,但有时可能要对这个过程进行控制。java可以将类声明为serial
izable,但仍可手工控制声明为static或transient的数据成员。
例子:一个非常简单的序列化类。

public class simpleSerializableClass implements Serializable{
    String sToday="Today:";
    transient Date dtToday=new Date();
}


序列化时,类的所有数据成员应可序列化除了声明为transient或static的成员。将变量声
明为transient告诉JVM我们会负责将变元序列化。将数据成员声明为transient后,序列化
过程就无法将其加进对象字节流中,没有从transient数据成员发送的数据。后面数据反序
列化时,要重建数据成员(因为它是类定义的一部分),但不包含任何数据,因为这个数据
成员不向流中写入任何数据。记住,对象流不序列化static或transient。我们的类要用
writeObject()与readObject()方法以处理这些数据成员。使用writeObject()与readObject()
方法时,还要注意按写入的顺序读取这些数据成员。
关于如何使用定制序列化的部分代码如下:

//重写writeObject()方法以便处理transient的成员。
public void writeObject(ObjectOutputStream outputStream) throws IOException{
    outputStream.defaultWriteObject();//使定制的writeObject()方法可以
                        利用自动序列化中内置的逻辑。
    outputStream.writeObject(oSocket.getInetAddress());
    outputStream.writeInt(oSocket.getPort());
}
//重写readObject()方法以便接收transient的成员。
private void readObject(ObjectInputStream inputStream) throws
IOException,ClassNotFoundException{
    inputStream.defaultReadObject();//defaultReadObject()补充自动序列化
    InetAddress oAddress=(InetAddress)inputStream.readObject();
    int iPort =inputStream.readInt();
    oSocket = new Socket(oAddress,iPort);
    iID=getID();
    dtToday =new Date();
}

 

完全定制序列化过程:

如果一个类要完全负责自己的序列化,则实现Externalizable接口而不是Serializable接口
。Externalizable接口定义包括两个方法writeExternal()与readExternal()。利用这些方
法可以控制对象数据成员如何写入字节流.类实现Externalizable时,头写入对象流中,
然后类完全负责序列化和恢复数据成员,除了头以外,根本没有自动序列化。这里要注意了。
声明类实现Externalizable接口会有重大的安全风险。writeExternal()与readExternal()
方法声明为public,恶意类可以用这些方法读取和写入对象数据。如果对象包含敏感信息,
则要格外小心。这包括使用安全套接或加密整个字节流。到此为至,我们学习了序列化的
基础部分知识。关于序列化的高级教程,以后再述。

posted @ 2007-06-08 13:39 小小程序程序员混口饭吃 阅读(957) | 评论 (1)编辑 收藏

1:redhat 语言设置 这个语言是安装的时候决定的,并不是每个user决定的

  /etc/sysconfig/i18n

2:redhat 模式

  /etc/inittab

id:5 xwindow  mode id:3 test mode

3:使用光驱

  挂载光驱mount /dev/hdc /mnt/cdrom

  卸载光驱时候出现 umount: /mnt/cdrom device is busy

  是因为当前的目录已经在光盘目录,应该先退出这个目录

4:安装rpm 文件

  rpm -ivh xxx.rpm  安装包

  rpm -qa |grep "tt*"  查询安装过的包

  rpm -e xxx


5:在text mode 上翻页 shift +pageup pagedown

6:ls -al
  查找隐藏的文件

7:set 查看环境变量  .bash_profile

  用户的语言设置与这个相关,如果没有设置会默认使用/etc/sysconfig/i18n

8:查看文件类型以及编码方式

  file *.file

9: 编码转换

命令名称:iconv
命令格式:iconv -f "文件目前编码" -t "文件转换后的编码" -o "转换后生成的新文件名" "源文件名"
ex: iconv -f ISO-8859 -t utf-8 -o mydoc.inc.php mydoc.inc.php.bak

 

 

 


 

posted @ 2007-05-21 17:31 小小程序程序员混口饭吃| 编辑 收藏
CMWAP 和 CMNET 只是中国移动人
为划分的两个GPRS接入方式。前者是为手机WAP上网而设立的,后者则主要是为PC、笔记
本电脑、PDA等利用GPRS上网服务。它们在实现方式上并没有任何差别,但因为定位不同
,所以和CMNET相比,CMWAP便有了部分限制,资费上也存在差别。

WAP只是一种GPRS应用模式,它与GRPS的接入方式是无关的。WAP应用采用的实现方
式是“终端+WAP网关+WAP服务器”的模式,不同于一般Internet的“终端+服务器”
的工作模式。主要的目的是通过WAP网关完成WAP-WEB的协议转换以达到节省网络流量和
兼容现有WEB应用的目的。WAP网关从技术的角度讲,只是一个提供代理服务的主机,它
不一定由网络运营商提供。但据我所知,中国移动GPRS网络目前只有唯一的一个WAP网关
:10.0.0.172,有中国移动提供,用于WAP浏览(HTTP)服务。有一点需要注意,WAP网
关和一般意义上的局域网网关是有差别的,标准的WAP网关仅仅实现了HTTP代理的功能,
并未完成路由、NAT等局域网网关的功能。这就决定了它在应用上所受到的限制。

为了从应用中区别两者的定位,中国移动对CMWAP作了一定的限制,主要表现在CMW
AP接入时只能访问GPRS网络内的IP(10..*),而无法通过路由访问Internet。我们
用CMWAP浏览Internet上的网页就是通过WAP网关协议或它提供的HTTP代理服务实现的。
也就是需要通过中国移动GPRS网络唯一的一个WAP网关:10.0.0.172。CMNET拥有完全的
Internet访问权,这里就不多说了,主要让我们来看看CMWAP。因为有了上面提到的限制
,CMWAP的适用范围就要看WAP网关所提供的支持了。目前,中国移动的WAP网关对外只提
供HTTP代理协议(80和8080端口)和WAP网关协议(9201端口)。

因此,只有满足以下两个条件的应用才能在中国移动的CMWAP接入方式下正常工作:
1. 应用程序的网络请求基于HTTP协议。2. 应用程序支持HTTP代理协议或WAP网关协议。
而cmnet则不受任何的限制。

说白了就是说通过cmwap的方式访问,需要走中国移动的网关通过http协议去连接,
这样的后果就是速度会变慢,相信很多朋友都用过代理服
务器吧,对,就是那个感觉,而通过cmnet来连接的,就是直接连接到无限乾坤在inter
net上的服务器,速度会比cmwap的快一些。说完了速度,就该说价格了,如果玩家没有
采用套餐的话,那cmwap和cmnet都是一样的,1kb三分钱,或者订了一个xx元包xM的套餐
,超出部分1k一分钱,这种时候,同等价格都一样,据我了解,cmwap版本流量会大一些
,所以还是用cmnet比较好,又快又省钱。但是对于很多地方的动感地带用户而言,情况
可能有些不同,相当一些地方的动感地带只能访问cmwap,不能访问cmnet,所以没地选
择了,还有一些地方有动感地带的包月上网卡,有10元、20元、50元的等等,具体的要
看当地的资费政策了,而这些包月卡通常只包cmwap的流量,这个时候如果用cmnet还要
另外付费,所以建议这些用户还是使用cmwap吧。最后总结一下,如果玩家的手机卡只能
访问cmwap或者有cmwap包月的套餐,那么您就使用cmwap连接来游戏,否则使用cmnet连
接是更好的选择


所以,一句话,有wap包月的地区就使用wap包月上网,没有包月业务的就用cmnet,反正都是按流量算钱,为什么不选择快一点的呢(但还是要提醒大家,按流量计费产生的费用是巨大的,要
多多注意)
posted @ 2007-05-17 10:50 小小程序程序员混口饭吃 阅读(1971) | 评论 (0)编辑 收藏
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class TestConn {

    
public TestConn() {
        
super();
    }


    
public static void main(String[] args) throws Exception {
        String url 
= null;
        getHttpText(url);
        System.out.println(
"abc");
    }


    
public static String getHttpText(String str) {
        URL url 
= null;
        
try {
            url 
= new URL(str);
        }
 catch (MalformedURLException e) {
            e.printStackTrace();
        }

        HttpURLConnection huc 
= null;
        
try {

            huc 
= (HttpURLConnection) url.openConnection();
            huc.setRequestMethod(
"GET");
            huc.setRequestProperty(
"Content-Type",
                    
"application/vnd.syncml.dm+xml");
            
// application/x-www-form-urlencoded
            
// application/vnd.syncml.dm+xml
            huc.setDoOutput(true);
            huc.setRequestProperty(
"Cache-Control""private");
            huc.setRequestProperty(
"Accept-Charset""utf-8");
            huc.setRequestProperty(
"Accept""application/vnd.syncml.dm+xml");
            huc.setRequestProperty(
"Content-Length""3");
            DataOutputStream printout;
            printout 
= new DataOutputStream(huc.getOutputStream());
            printout.writeBytes(
"abc");
        }
 catch (IOException e) {
            e.printStackTrace();
        }

        InputStream is 
= null;
        
try {
            is 
= huc.getInputStream();
        }
 catch (IOException e) {
            e.printStackTrace();
        }

        BufferedReader br 
= new BufferedReader(new InputStreamReader(is));
        StringBuffer sb 
= new StringBuffer();
        String line 
= "";
        
try {
            
while ((line = br.readLine()) != null{
                sb.append(line).append(
"\n");
            }

        }
 catch (IOException e) {
            e.printStackTrace();
        }

        
return sb.toString();
    }


}

posted @ 2007-05-14 09:16 小小程序程序员混口饭吃 阅读(4062) | 评论 (0)编辑 收藏
记事本=notepad
计算器=calc
注册表=regedit
系统检测=dxdiag
画图=mspaint
远程桌面=mstsc
posted @ 2007-04-29 17:27 小小程序程序员混口饭吃 阅读(486) | 评论 (1)编辑 收藏
 其实这个问题不是程序的问题,主要是property中文问题,这个问题可以通过build解决掉

 <native2ascii src="." dest="build" includes="*Props.txt" />
把配置文件编码 windows下默认GBK编码,linux 要加encoding
代码一行不用改,放心汉化吧~~
posted @ 2007-04-24 15:21 小小程序程序员混口饭吃 阅读(1909) | 评论 (3)编辑 收藏
如题,有没有朋友知道开源的在线图片处理的程序,在页面上直接处理图片,有点象iephotoshop,功能即使不如imageJ,也要有一些基本的功能.
posted @ 2007-04-19 09:20 小小程序程序员混口饭吃 阅读(2082) | 评论 (2)编辑 收藏
话说“你不理财,财不理你”

那么什么是理财呢???

很多人都很知道“理财”,也都无时无刻不在理财,但把理财说清楚的人却不多...

很多人说到理财想到的就是投资,就是开源节流,就是合理分配财产,等等… …

其实,
---------------------------------------------------------
理财就是对财富的有效管理。

理财的内涵很广,包括开源节流,包括合理分配财产,包括投资增值等,但又不止于这些。从理财的基础理论来讲,主要包括:现金管理、资产管理、债务管理、风险管理、投资管理等等。
---------------------------------------------------------
现金管理是理财的基础。包括各项收入的筹划和管理,包括各项税费的管理,包括各项日常支出的管理,包括现金的积累和短期储蓄等等。具体的管理工具和形式有各式各样的银行卡片,各式各样的储蓄方式,各种各样的支出方式,包括各种各样的节俭手段等等。

资产管理是理财的重心。资产具体包括固定资产、流动资产等。固定资产比如房产、铺面等等,流动资产包括储蓄资产、投资资产、保险资产等。资产管理是家庭理财的重点,合理有效的管理需要。

债务管理是理财的关键。债务并非完全的坏事,合理的管理债务是迅速达到理财目标的捷径,只要把债务控制在一定的合理的范围之内,对优化财务结构有很好的作用。比如在财力许可的情况下可以通过按揭提前实现高品质的家庭生活,通过金融信用延迟支付货款往来等,从而更快实现财务目标。

风险管理是理财的关键。有效的风险管理是现代社会先进的标志,没有对风险的管理交通工具不能上路运营,贸易货运不能出门出海流通,商场大厦无法入住营业,流动性和小家化也决定个人进行风险管理是大势所趋。

投资管理是理财的要点。现在很多对投资理财非常渴望,一提到投资赚钱眼睛就发亮,主要是因为目前我国金融环境不够完善,安全稳健的大众投资品种非常匮乏,很多人的收益局限于2个点以内,相较于去年初高达5个点的通货膨胀显然是一个很大的威胁。而国内居民的投资信息和能力先天不足,稍有异动即可能遭遇陷阱的现状导致国民储蓄逐年逼高。在理财范畴内投资增值是最需要专业知识的,也是实现家庭理财目标最关键的步骤。所以如何实现投资的有效管理就很重要。


总之,理财就是所有与财富有关的活动的总称,是现代社会重要的组成要素,是现代人过上幸福快乐生活必备的基本素质。

而且,五个理财的基本方面也是互相关联,互为制约,相互促进的。

posted @ 2007-02-13 11:07 小小程序程序员混口饭吃 阅读(350) | 评论 (0)编辑 收藏

           

做为新一代 3G 及移动终端浪潮的设备管理平台, OMA DM 技术获得了众多设备厂商和运营商的追捧,也为软件开发商提供新的崛起机会。业内目前也有不少工作在做这方面的软件。好多公司这方面的产品都是基于Sync4J开发的。

Sync4J 开源项目为我们提供了完整的 OMA DM 1.1.2 规范的 Java 实现。本文记录了 Sync4J DM Server 安装以及使用SCTS模拟器来模拟手机做一个DM业务,本文没有用PPG来通过短信方式来用真手机来做,只是用模拟器来做的。SCTSOMA官方提供的一个测试工具,主要用来测试DMserver的,这里我们用来测试Sync4JSync4JSCTS的集合是我们学习OMA的一个很好的方式。

1 :用到以下工具。

  Oracle9i

  jboss-3.2.3

  sync4j-server-dm-1.4.9   sync4j 官方有下载

  SCTS_DeviceManagement_v1.12.zip  OMA 官方网站有下载。

 

 

2 :安装调试

  2.1 解压文件:

   jboss-3.2.3 解压到 C:\jboss-3.2.3

sync4j-server-dm-1.4.9 解压到 D:\sync4j\all\server-dm .

直接安装 SCTS.

  2.2 配置环境变量

  JAVA_HOME=

  J2EE_HOME= C:\jboss-3.2.3

  SYNCSERVER_HOME= D:\sync4j\all\server-dm

2.3 修改SYNCSERVER_HOME下的几个配置文件

   SYNCSERVER_HOME\ default\config\common\properties\ Sync4j.properties

把第一行改为 server.uri=http://your IP:8080/sync4j-dm/dm

  SYNCSERVER_HOME\ install.properties 改为

(1)server-name=http://10.150.4.7:8080/sync4j-dm/dm

 (2) oracle 的数据库,以下是用来连接数据库的,所以一定要配置正确。

jdbc.classpath=C:\\jboss-3.2.3\\server\\all\\lib\\ojdbc14.jar

jdbc.driver=oracle.jdbc.driver.OracleDriver

jdbc.url=jdbc:oracle:thin:@11.11.11.11:1521:abc

jdbc.user=sync4j

jdbc.password=sync4j

2 4以上都做完后用Sync4j自己带的安装脚本安装sync4j dm server

SYNCSERVER_HOME 下运行 bin\install.cmd jboss32

2 5由于这个版本存在了一个bug,所以在2.4做完后要修改

SYNCSERVER_HOME\bin\start.cmd

把倒数第三行 call\run.bat -c sync4j 改为

call %J2EE_HOME%\bin\run.bat -c sync4j

2 6 SYNCSERVER_HOME 运行 bin\start.cmd安装

所有程序到安装到了 jboss_home 下了,可以到 JBOSS_HOME\ server\sync4j 就可以看到了,看一下你的 oralce 库里面也初始化了数据,表也建好了。

 

2 7 添加一个手机(我们其实是个模拟器)上来

http://your ip:8080/dmdemo/jsp/addDevice.jsp 填写一个 IMEI:111111111111111,

 

2 8 配置scts

Add device : IMEI:111111111111111 然后点 apply

点击 DM Account

Name sync4j

Server:sync4j

Con : 不用填写

Address http://your ip /sync4j-dm/dm

Port :8080

Server authentication:

  Digest : 找数据库用 sync4j 的数据库中, sycn4j_device 表中 :IMEI:111111111111111 server password 为: srvpwd, 把这个 password 填写到 password 中。

Client authentication

   DIGEST: USER NAME: sync4j PASSWORD: sync4j

Add 就可以了

然后点 connect 连一下 DM SERVER 看看能否连上。 第一次一般会出现认证错我,接着再联一次就可以了, SCTS 有日志可以查看。

 

如果连通了那下面就来做一个采集模拟器上的一个节点吧。

 

http://your ip:8080/dmdemo/index.html

device id IMEI:111111111111111 login

1.JPG

 

  然后点击 add to operation list

2.JPG

然后用 SCTS 主动回联一下,看看 server 能够拿到这个节点的值

3.JPG

你会看到 6 message !!!

详细看一下这 6 message 你会发现,这个节点的采集已经成功了!

 

 

 

 

posted @ 2007-02-05 10:02 小小程序程序员混口饭吃 阅读(9269) | 评论 (11)编辑 收藏

 

 1 import  java.io.BufferedReader;
 2 import  java.io.InputStreamReader;
 3 import  java.security.MessageDigest;
 4
 5 import  sun.misc.BASE64Decoder;
 6 import  sun.misc.BASE64Encoder;
 7
 8 public   class  ConvertNounce  {
 9
10      //  Digest = H(B64(H(username:password)):nonce)
11      //  b1=B64(H(username:password));
12      //
13      //
14      /**
15      *  @param  args
16       */

17      public   static   void  main(String[] args)  throws  Exception  {
18         
19
20         
21      //     if(args.length!=3) throw new Exception("args is wrong ,there is must by three args :username password nextNounce");
22
23         InputStreamReader reader  =   new  InputStreamReader(System.in);
24         BufferedReader input  =   new  BufferedReader(reader);
25     
26         
27         System.out.println( " input username: " );
28         String username  = input.readLine();
29         System.out.println( " input password: " );
30         String pwd  =  input.readLine();
31         System.out.println( " input nextNounce: " );
32         
33         String serverNounce  =  input.readLine();
34         String clientNounce  =   null ;
35
36         System.out.println( "" );
37         
38         System.out.println( " userName= " + username);
39         System.out.println( " password= " + pwd);
40         System.out.println( " nextNounce= " + serverNounce);
41          byte [] b1  =  calculateDigestAndEcode64(username, pwd);
42         
43      //     System.out.println("b1="+new String(b1));
44         
45          // server 下来的nounce一定要先做B64的解码,否则算出来的结果对不上
46         serverNounce  = new  String( new  BASE64Decoder().decodeBuffer(serverNounce));
47         
48      //     System.out.println(serverNounce);
49
50          byte [] bserverNounce  =  serverNounce.getBytes();
51
52          byte [] buf  =   new   byte [b1.length  +   1   +  bserverNounce.length];
53
54         System.arraycopy(b1,  0 , buf,  0 , b1.length);
55
56         buf[b1.length]  =  ( byte ' : ' ;
57         System.arraycopy(bserverNounce,  0 , buf, b1.length + 1 ,
58                         bserverNounce.length);
59         MessageDigest md  =  MessageDigest.getInstance( " MD5 " );
60         
61      //     System.out.println(new String(buf));
62
63          byte [] digest  =  md.digest(buf);
64         
65      //     System.out.println(new String(digest));
66
67         clientNounce  =   new  BASE64Encoder().encode(digest);
68         System.out.println( "" );
69         System.out.println( " result Nounce= " + clientNounce);
70         
73     }

74
75      public   static   byte [] calculateDigestAndEcode64(String username,
76             String password)  throws  Exception  {
77
78         MessageDigest md  =  MessageDigest.getInstance( " MD5 " );
79         String cred  =   "" ;
80          if  (username  !=   null {
81             cred  =  username.trim();
82         }

83         cred  +=   " : " ;
84          if  (password  !=   null {
85             cred  +=  password.trim();
86         }

87      //     System.out.println(cred);
88          //  System.out.println(new String(md.digest(cred.getBytes())));
89          return   new  BASE64Encoder().encode(md.digest(cred.getBytes()))
90                 .getBytes();
91     }

92     
93     
94
95 }

96
posted @ 2007-01-11 14:57 小小程序程序员混口饭吃 阅读(1351) | 评论 (0)编辑 收藏

范伟先生名言:猪撞树上了,你撞猪上了吧

  我有4种理解:
      1:猪撞树上了,你撞在猪上,猪比较软,你比猪幸运
      2:人家猪都撞树上了,你又往人家身上撞,不想让猪活了?
      3:猪往树上撞,他智商低,你比不过他,去撞猪泄愤啊?
      4:你撞了猪,猪不跟你一般见识,他去撞树

posted @ 2006-12-19 09:31 小小程序程序员混口饭吃 阅读(1647) | 评论 (6)编辑 收藏

最近写一个东西,在网上看到这个计划书的范本,很不错,抄下来

商业计划书目录



报告目录

第一部分 摘要(整个计划的概括) (文字在2-3页以内)



一. 项目简单描述(目的、意义、内容、运作方式)

二. 市场目标概述

三. 项目优势及特点简介

四. 利润来源简析

五. 投资和预算

六. 融资方案(资金筹措及投资方式)

七. 财务分析(预算及投资报酬)



第二部分 综述



第一章 项目背景

一. 项目的提出原因

二. 项目环境背景

三. 项目优势分析(资源、技术、人才、管理等方面)

四. 项目运作的可行性

五. 项目的独特与创新分析

第二章 项目介绍

一. 网站建设宗旨

二. 定位与总体目标

三. 网站规划与建设进度

四. 资源整合与系统设计

五. 网站结构/栏目板块

六. 主要栏目介绍

七. 商业模式

八. 技术功能

九. 信息/资源来源

十. 项目运作方式

十一.网站优势(资源/内容/模式/技术/市场等)

十二.无形资产

十三.策略联盟

十四.网站版权

十五.收益来源概述

十六.项目经济寿命



第三章. 市场分析

一. 互联网市场状况及成长

二. 商务模式的市场地位

三. 目标市场的设定

四. 传统行业市场状况(网站市场资源的基础)

五. 市场定位及特点(消费群体、消费方式、消费习惯及影响市场的主要因素分析

市场规模、市场结构与划分,特定受众等

六. 市场成长(网站PageView与消费者市场)

七. 本项目产品市场优势(对于特定人群的市场特点的省事、省时、省力、省钱等)

八. 市场趋势预测和市场机会

九. 行业政策

第四章 竞争分析

一. 有无行业垄断

二. 从市场细分看竞争者市场份额

三. 主要竞争对手情况

第五章 商业实施方案

一. 商业模式实施方案总体规划介绍

二. 营销策划

三. 市场推广

四. 销售方式与环节

五. 作业流程

六. 采购、销售政策的制定

七. 价格方案

八. 服务、投诉与退货

九. 促销和市场渗透(方式及安排、预算)

1. 主要促销方式

2. 广告/公关策略、媒体评估

3. 会员制等

十. 获利分析

十一. 销售资料统计和销售纪录方式,销售周期的计算。

十二. 市场开发规划,销售目标(近期、中期),销售预估(3-5年)销售额、占有率及

计算依据



第六章 技术可行性分析



一. 平台开发

二. 数据库

三. 系统开发

四. 网页设计

五. 安全技术

六. 内容设计

七. 技术人员

八. 知识产权

第七章 项目实施

1. 项目实施构想(公司的设立、组织结构与股权结构)

2. 网站开发进度设计与阶段目标

3. 营销进度设计与阶段目标

4. 行政管理部门的建立、职工的招募和培训安排

5. 项目执行的成本预估



第八章 投资说明



一. 资金需求说明(用量/期限)

二. 资金使用计划(即用途)及分期

三. 项目投资构成和固定资产投资的分类

四. 主要流动资金构成

五. 投资形式(贷款/利率/利率支付条件/转股-普通股、优先股、任股权/对应

价格等)

六. 资本结构

七. 股权结构

八. 股权成本

九. 投资者介入公司管理之程度说明

十. 报告(定期向投资者提供的报告和资金支出预算)

十一. 杂费支付(是否支付中介人手续费)

第九章 投资报酬与退出

一. 股票上市

二. 股权转让

三. 股权回购

四. 股利



第十章 风险分析与规避

一. 政策风险

二. 资源风险

三. 技术风险

四. 市场风险

五. 内部环节脱节风险

六. 成本控制风险

七. 竞争风险

八. 财务风险(应收帐款/坏帐/亏损)

九. 管理风险(含人事/人员流动/关键雇员依赖)

十. 破产风险

第十一章 管理



一. 公司组织结构

二. 现有人力资源或经营团队

三. 管理制度及协调机制

四. 人事计划(配备/招聘/培训/考核)

五. 薪资、福利方案

六. 股权分配和认股计划



第十二章 经营预测

一. 网站经营

1.访问人数成长预测

2.会员增长预测

3.行业联盟预测

二. 销售数量、销售额、毛利率、成长率、投资报酬率预估及计算依据

第十三章 财务可行性分析

一. 财务分析说明

二. 财务数据预测

1. 收入明细表

2. 成本费用明细表

3. 薪金水平明细表

4. 固定资产明细表

5. 资产负债表

6. 利润及利润分配明细表

7. 现金流量表

三. 财务分析指标

反映财务盈利能力的指标

a.投资回收期(Pt)

b.投资利润率

c.投资利税率

d.不确定性分析



第三部分 附录

一. 附件



1. 主要经营团队名单及简历

2. 专业术语说明

3. 企业形象设计/宣传资料(标识设计、说明书、出版物、包装说明等)



二. 附表



1. 市场受众分析(人群分布/数量等)表

2. 互联网成长状况表

3. 主要设备清单

4. 互联网市场调查表

5. 预估分析表

6. 各种财务报表及财务预估表

posted @ 2006-12-18 13:48 小小程序程序员混口饭吃 阅读(10618) | 评论 (2)编辑 收藏

 

1: 下载 cvsnt-2.5.03.2382(http://www.cvsnt.org)

2: 安装完全采用默认就可以了,安装完可以不重启

3 :开始菜单 ->CVSNT-> Control Panel . 停止 CVS NT

 

4 :进入 repository configuration 点击 add 添加一个如图所示:

   Localtion  填写一个 D:/CVSRoot

   Name     填写 /cvs

 

 

 

 

 

  

cvs_rep.GIF 

5 :进入 server settting

 

 

CVS_server_setting.GIF 

  Run as 选择一个 windows 下已有用户比如 (administrator) ,其余不用修改,应用就可以了。

6 :进入 about :CVSNT 启动 . CVS 已经配置完毕,至于安全什么方面的东西我没有弄过。

 

7: 打开 eclilpse ,file->new->other ,CVS

 

 CVS_ECLIPSE1.GIF

 

 

CVS_ECLIPSE2.GIF 

 

 

输入 Host repository path 、用户名、密码 ,其余默认,然后 next

CVS_ECLIPSE3.GIF 

 

Next

 

CVS_ECLIPSE4.GIF 

Next

 

CVS_ECLIPSE5.GIF 

Next

 

CVS_ECLIPSE6.GIF 

 

一切搞定,你可以建立一个目录然后 就可以commit .

posted @ 2006-12-14 16:14 小小程序程序员混口饭吃 阅读(13061) | 评论 (6)编辑 收藏
1、长的惊险.....

2、你小时候被猪亲过吧?

3、你长的很 爱guo 很 敬业 很 有骨气

4、长得真有创意,活得真有勇气!

5、你长的真t m 后现代

6、你长的好象车祸现场

7、你长的外形不准 比例没打好

8、你干嘛用屁股挡住脸啊!

9、我觉得世界上就只有两种人能吸引人,一种是特漂亮的 一种就是你这样的

10、你的长相很提神的说!!

11、你需要回炉重造

12、他们怎么能管你叫猪呢??这太不像话了!总不能人家长的像什么就叫人家什么吧!怎么能说你长得像猪呢?那是侮辱了猪。

13、*,你T.M.D.长得太好认了。

14、长的很科幻,长的很抽象!

15、见过丑的,没见过这么丑的。乍一看挺丑,仔细一看更丑!

16、长的很无辜,长的对不起人民对不起党。

17、你长的拖慢网速,你长的太耗内存

18、你光着身子追我两公里 我回一次头都算我是流氓!

19、大哥,把你脸上的分辨率调低点好吗?

20、你长的违...

posted @ 2006-12-13 10:49 小小程序程序员混口饭吃 阅读(468) | 评论 (0)编辑 收藏
今天看到一篇非常好的文章,忍不住copy下来。
有一天,柏拉图问老师苏格拉底什么是爱情?
老师就让他先到到麦田里去,摘一棵全麦田里最大最金黄的麦穗来,期间只能摘一次,并且只可向前走,不能回头。
柏拉图于是按照老师说的去做了。结果他两手空空的走出了田地。老师问他为什么摘不到?他说:因为只能摘一次,又不能走回头路,期间即使见到最大最金黄的,因为不知前面是否有更好的,所以没有摘;走到前面时,又发决总不及之前见到的好,原来最大最金黄的麦穗早已错过了;于是我什么也没摘。
老师说:这就是“爱情”。
之后又有一天,柏拉图问他的老师什么是婚姻,他的老师就叫他先到树林里,砍下一棵全树林最大最茂盛、最适合放在家作圣诞树的树。其间同样只能砍一次,以及同样只可以向前走,不能回头。
柏拉图于是照着老师的说话做。今次,他带了一棵普普通通,不是很茂盛,亦不算太差的树回来。老师问他,怎么带这棵普普通通的树回来,他说:“有了上一次经验,当我走到大半路程还两手空空时,看到这棵树也不太差,便砍下来,免得错过了后,最后又什么也带不出来。”
老师说:“这就是婚姻!” 人生就正如穿越麦田和树林,只走一次,不能回头。要找到属于自己最好的麦穗和大树,你必须要有莫大的勇气和付出相当的努力
posted @ 2006-12-12 13:21 小小程序程序员混口饭吃 阅读(468) | 评论 (1)编辑 收藏

 

FUMO (Firmware Update Management Object) 手机终端用来固件升级的协议。协议主要规定了一下方面:

1 FIRMWARE UPDATE MANAGEMENT OBJECT PARAMETERS. (路径和节点)

2 BEHAVIOR ASSOCIATED WITH THE MANAGEMENT OBJECT (执行升级和下载的命令以及 ALERT

3 CLIENT INITIATED FIRMWARE UPDATE ( 手机自行发起的固件升级的一些规定 )

 

1 FIRMWARE UPDATE MANAGEMENT OBJECT PARAMETERS

 FUMO_1_PRA.GIF

 

总共定义如上节点

 

PKNAME: 升级包名字

Pkgversion: 升级包版本

Download :用来执行初始化下载的节点

PKGURL: 初始化下载时存储的下载地址的节点

Update: 用来执行升级的节点

Pkgdata: 用来提供升级包数据的节点

Downloadnadupdate :用来初始化下载和升级的节点

    Pkgurl : 初始化下载时存储的下载地址的节点

State :手机当前升级过程中的状态。

Ext :厂商自己定义的扩展节点

 

根据实现不同, FUMO 可以选择 Downloadnadupdate 也可以选择 downd and upate 2 个节点的组合来实现固件的升级 ( 先下载,把下载的东西放在 X/update/pkgdata 里面,然后执行升级 )

 

State 有一下状态

FUMO_2_STATE.GIF 

升级成功返回 100 ,根据返回的不同状态,来与 SERVER 交互。

 

Fumo 规定的升级过程中的流程

 

FUMO_3_FLOW.GIF 

 

  FUMO 从初始化下载到最后成功然后清除掉下来后的升级包的全过程,

 

 

2 BEHAVIOR ASSOCIATED WITH THE MANAGEMENT OBJECT

 

FUMO 在执行的开始,假定手机采用先 download 然后 update, 先把升级包的 URL SERVER 发过来 , 手机先自行 replace 命令把 URL 放在 Download/PkgURL 下面,然后执行 exec 命令把包下载到 update/PkgData 下面,(有的 FUMO 实现厂商采用差分包方法升级)在 update 的时候直接执行 exec 执行升级。

 

 

 

 

以下分别是执行了 2 exec 分别在执行 download downloadandupdate.

FUMO_4_DOWNLOAD_UPDATE.bmp
FUMO_5_DOWNLOAD_AND_UPDATE.GIF 

 

下图是手机在进行升级过程中返回给 SERVER 的一些结果,都是用数字来表示, server 可以根据这些返回码来判断终端在升级过程中哪一步执行失败。

 

 

 FUMO_6_RESULTCODE.GIF  

 

 

 

下图是一个终端在执行一个 download 过程和一个 update 过程的流程图,此图能够清晰的显示出 DM command fumo 的节点如何交互的。

FUMO_7_FLOW_D_U.GIF 

下图是一个直接的 DownloadAndUpdate 的过程。手机一般会选择这两种的中的一种方式。

FUMO_8_FLOW_DANDU.GIF 

3 CLIENT INITIATED FIRMWARE UPDATE

其实这是 CP 协议的一部分内容,在下一篇文章会详细的描述 cp 协议的一些东西, cp 协议想关联有好几协议。

posted @ 2006-12-08 15:43 小小程序程序员混口饭吃 阅读(2181) | 评论 (4)编辑 收藏

 DM并不是一个前沿的技术。据悉,韩国SK电讯、日本NTT DoCoMoKDDI以及以Vodafone为首的一些欧洲运营商都已经建立起了一定规模的DM体系,它们或根据自行标准,或遵循OMA标准,现在主要提供的是以FOTA(固件更新)为主的基本功能,将来还可支持数据备份、诊断及故障修复、图形用户界面处理,甚至病毒防护等多种功能。

因为设计缺陷,Sony Panasonic 曾经为手机召回蒙受了上亿美元的损失,同时中国建立手机召回制度的呼声越来越高,通信厂商该如何应对?如果因为BUG而召回手机那么岂不损失太大。终端管理在这种情况下应运而生,可以给厂商减少损失。

一句话,只要能上网支持DM的手机未来就可以在线升级操作系统,以及修复BUG等等,手机厂商和运营商会更加方便,节省成本,同时能给客户带来更好的体验。只要手机安装了支持DM协议的软件,同时有一个与之交互的SERVER,一切问题迎刃而解。


FOTA有多种实现方式,DM便是其中的一个协议

Dm
协议 5 package.

 

 

 DM_PHASE.GIF

 

 

 

1: package0 server 发送通知(一般是短信)给 CLIENT ,一般通过 WAP PUSH 下去给手机。

 

2: package1

 

手机收到后 wap push 的东西后,根据 WAP PUSH 相关协议,手机会自动回联回 SERVER server 会得到手机的 imei, 厂商、型号等基本信息。

 

3:package2

 

Server 收到 client 的回复后,得到手机的 IP ,然后通过 HTTP 请求 client ,发送一个用户确认请求(手机必须能通过 GPRS 等方式上网),

 

 

4:package3

 

  手机收到后,如果用户确认 DM 继续进行,如果用户否认 DM 发送给手机一个结束标志。就是说不管 package3 用户是否确认或否认 package4 都会进行下去

 

5:package4

 

 SERVER 收到用户返回的信息不管是确认还是否认都会回复,如果 server 还想继续进行下去,那么会重复 package2 ,只是不再是简单让用户确认的东西,比如其他业务通过 DM 去取用户的版本的信息比如发送一个 GET command ,最后一个 package 永远是没有任何 command 的。就是说 package2,package3 可以重复进行多次

 

DM_CHART.GIF

1101:等待用户确认
1200:终端回联SERVER
1201:终端发起
1222:更多的message
1223 :session abort

posted @ 2006-12-08 11:21 小小程序程序员混口饭吃 阅读(2456) | 评论 (0)编辑 收藏
      事务是用来保证数据的一致性( integrity )而锁是保证数据的并发(控制多个事务的并发)( concurrency )。   锁的级别越高,可能会影响数据库的并发。锁的级别越低一般来说数据库的并发越好。   锁在 JDBC,JTA 以及容器管理的事务中的用法基本一样,也有写不同,主要在 JTA 分布式事务上个别又差异。 事务只是用来保证,数据一致性,一致性包括 : 能否保证与其他事务的隔离,以及能否在同一事务中保证重复读,脏读,脏写等等方面。   Oracle 在不是手工加锁的情况下, ORACLE 会自动调度锁。 ORACLE 自动调度锁得执行顺序,一般不会发生死锁现象。有些数据库会自动调度数据库锁得级别,这就增加了死锁的可能, ORACLE 永远不会自动调度锁的级别,死锁发生时, oracle 也会去自动调度,这要延时一段时间, ORACLE 自己的策略,会 ROLLBACK 一个事务,以保证发生死锁的 2 个事务都执行下去。   锁的种类很多,有 DML,DDL 锁以及其他,平时我们开发过程中主要是 DML,DDL 锁。 DML 锁又分很多方面:
RS: row share RX: row exclusive S: share SRX: share row exclusive X: exclusive  
( 1 ) RS 可以通过一下声明方式来锁定表的行
SELECT ... FROM table ... FOR UPDATE OF ... ; 

LOCK TABLE table IN ROW SHARE MODE;

一旦被 RS 锁定,不允许再对表进行 LOCK TABLE table IN EXCLUSIVE MODE

( 2 ) RX 可以通过一下声明方式来锁定表的行
INSERT INTO table ... ;

UPDATE table ... ;

DELETE FROM table ... ; 

LOCK TABLE table IN ROW EXCLUSIVE MODE;
一旦通过 RX 锁定了表中的行,不允许对表进行下列操作

LOCK TABLE table IN SHARE MODE; 

LOCK TABLE table IN SHARE EXCLUSIVE MODE;

LOCK TABLE table IN EXCLUSIVE MODE;


( 3 ) s ( share table lock )可以通过以下方式锁定表
LOCK TABLE table IN SHARE MODE (可以说有多个 S 锁定一个表) ;
允许进行的操作,所有的查询以及 SELECT ... FOR UPDATE, 和 LOCK TABLE ... IN SHARE MODE ,只允许本事务内更新数据( update ,这种情况也是只允许当前表上就一个 S 锁)
不允许的操作
LOCK TABLE table IN SHARE ROW EXCLUSIVE MODE;

LOCK TABLE table IN EXCLUSIVE MODE;

LOCK TABLE table IN ROW EXCLUSIVE MODE;
( 4 ) SRX 通过以下方式锁定表
LOCK TABLE table IN SHARE ROW EXCLUSIVE MODE;
比 S 少了一点,这里只是允许一个 SRX 锁定一个表
不允许的操作:
LOCK TABLE table IN SHARE MODE;

LOCK TABLE table IN SHARE ROW EXCLUSIVE MODE;

LOCK TABLE table IN ROW EXCLUSIVE MODE;

LOCK TABLE table IN EXCLUSIVE MODE;
( 5 ) X 级别最高的锁定形式: LOCK TABLE table IN EXCLUSIVE MODE;
只允许其他事务 QUERY 不允许其他操作。

Table 13-4 Locks Obtained By DML Statements
DML Statement Row Locks? Mode of Table Lock
SELECT ... FROM table   
INSERT INTO table ... X RX
UPDATE table ... X RX
DELETE FROM table ... X RX
SELECT ... FROM table ...    FOR UPDATE OF ... X RS-
LOCK TABLE table IN ...    
ROW SHARE MODE   RS
ROW EXCLUSIVE MODE   RX
SHARE MODE   S
SHARE EXCLUSIVE MODE   SRX
EXCLUSIVE MODE   X
 

       














这个表上很清楚
posted @ 2006-11-30 10:36 小小程序程序员混口饭吃 阅读(4517) | 评论 (2)编辑 收藏
转自http://www.blogcn.com/user64/5635/index.html
1、很快你就会发现几千元的工资不算什么
2、很快你就会发现金钱的获得是以时间和个人生活的牺牲为代价的
3、很快你就会发现自己有点小钱但不幸福
4、很快你就会讨厌自己,讨厌自己的复杂和世故
5、很快你就会发现你身边的很多人怎么素质这么低,这么俗,而你也快成为这样的 了
6、很快你就会讨厌冬天的,太冷了,太冷清和寂寞了
7、你会不断地觉醒,不断地继续奋斗,然后你老想着辞职休息,或者再读书,或者不再创业
8、你会偶尔去同学录看看,但你已经不想再说话了
9、你会偶尔想起自己以前最好的朋友,然后给他/她打个无聊的电话
10、你会偶尔给自己的初恋情人打个电话,然后你发现自己老了
11、你甚至会发现自己现在成熟得可怕,一件很复杂的事情,你一眼就看穿了,而你的依据是你对黑暗的了解
12、你想幸福就要自己花一生的时间去先痛苦
13、当你工作后发现你喜欢摇滚乐的时候,证明你还在挣扎;当你工作后发现自己喜欢忧郁的轻音乐时,你就快完蛋了; 工作了才知道,有空调的办公室,不如闹哄哄的教室;工作了才知道,大学里爱情是游戏,现在爱情是交易;工作了才知道 有时候一顿饭吃上千块也是一种需要;工作了才知道,学生都是装大款,真正的有钱人都哭穷;工作了才知道,穿什么不取决与品位,取决与场合;工作了才知道,学校三点一线,现在却是画直线;工作了才知道,原来买房子也是个远大的理想;工作了才知道,成为社会精英的几率,和中彩票是一样的;工作了才知道,原来消灭剥削只是一种传说;工作了才知道,自立的代价是失去更多的自由


posted @ 2006-11-28 15:57 小小程序程序员混口饭吃 阅读(513) | 评论 (1)编辑 收藏
     摘要: 做技术支持 2 个月了,也就是说有 2 个月没有碰代码了,手都很生了,最近遇到项目大的并发问题,数据也有些不太正确,就想到了项目中,由于模块过多,异步的情况也有发生,所以想到事务与锁的相关知识,先写一点事务相关的理解,然后写一点锁相关的东西,以便加深自己的理解。   ...  阅读全文
posted @ 2006-11-16 13:48 小小程序程序员混口饭吃 阅读(2764) | 评论 (3)编辑 收藏
最近韩国房价失控上涨,有关职能部门3高官引咎辞职.

房价疯涨在中国似乎是司空见惯,习以为常,老百姓也几乎麻木,买不起房子的年轻人只能坐以待毙,泱泱大国除了几个学者能够抨击一下之外,好像没有人说要出来承担责任,政府跟房地产商一个论调,
社会需求导致房价不可能跌。房产商可以控制一些主流的媒体,就跟一些民办学校控制当地的报纸一样,你们敢揭露我,我就不去你们那里打广告,一年让你们少赚个几百万,这些主流媒体当然不会放弃
这么大的摇钱树,也就厚着脸去低三下四了。房子还是疯了一样的涨,恐怕永远没有父母官出来辞职的
除非被利益集团排挤下来。地价高,商业贿赂,行业不正规,职能部门的监管,以及法制整体不健全导致房价疯长,归根结底:房价高总是由上层的利益集团控制的,老百姓只能叹气的份。

联想到,最近台湾政坛,至少那也是民主,香港一个歌星的老爹收了几百万港元就是特大受贿罪犯,这在中国简直是小巫见大巫,种种情况表明大陆还是有差距的,不过最新全球廉政指数,中国上升了10多位,我们也相信是新一代政府正在加强这方面的建设。我爱我的国家,我有理由相信,新一代政府会越来越好,大家拭目以待。

加油中国!


posted @ 2006-11-16 08:51 小小程序程序员混口饭吃 阅读(691) | 评论 (2)编辑 收藏
     摘要: 文章转自网上好像是玉米田的,忘记了锁( locking ) 业务逻辑的实现过程中,往往需要保证数据访问的排他性。如在金融系统的日终结算 处理中,我们希望针对某个 cut-off 时间点的数据进行处理,而不希望在结算进行过程中 ...  阅读全文
posted @ 2006-11-15 08:35 小小程序程序员混口饭吃 阅读(51648) | 评论 (23)编辑 收藏
一个傻子买了3个大饼,吃了前两个都没吃饱,到第三个才吃饱。于是叹道:早知道,我就只买第三个了,前两个饼没用.我们又何尝不是这种人?我们也经常喟叹自己不能成功。
     其实没有人能够随便成功,一口吃饱也是不可能的,所以平时必须打好基础,成功总是属于有准备的人,平时多积累,说不定哪天就会成功!
posted @ 2006-11-10 13:26 小小程序程序员混口饭吃 阅读(377) | 评论 (0)编辑 收藏
超市自造三千元笔记本10天卖出5台,这是刚刚在DONEWS上看到的消息,据物美集团副总裁吴坚中介绍,这款自有品牌笔记本电脑定名为“优宜”,意为“质优价廉”,由物美和合作厂家威盛电子(中国)有限公司联合推出。据其介绍,这款笔记本电脑最低售价才3200元一台,配置稍好的价格才3649元。

原来生产厂家开始物色新的渠道,传统的大商场 ,家电卖场,已经没有太多的利润点,就是说渠道把厂家的利润给吃个差不多了,厂家必须寻找新的渠道,既给国美等大卖场施加了压力,又给自己寻找了利润空间,消费者也得到了实惠,看样子这款比较本只是厂家小试牛刀,如果这种模式能够成功,毕竟带来卖场新一轮冲击,在中国得渠道者得天下,厂商卖本子在传统卖场赚得试卖白菜得钱,利润都被渠道压缩了。
我们拭目以待。
posted @ 2006-11-08 09:07 小小程序程序员混口饭吃 阅读(624) | 评论 (3)编辑 收藏
find 命令在linux中是很常用到的一个查找命令,它的功能非常地强大。可以结合正则匹配来搜索系统中的指定的内容,以下我就记录一下这个find常用到的一些用法

 

首先我们来看年find的总体用法

find path option [-print -exec -ok]

其中path是指定在哪个路径中查找内容。如/var下查找内容,option是find中的一些属性值,常用的有-name,-type,-mtime,-ctime,-atime,-user,-group,-nouser,-nogroup,-perm等,[-print -exec -ok]是可选属性值,-print是指把查找到的内容输出到指定的地方,-exec与-ok都是执行另处的command命令,但两都也有一点不同,-exec在执行指定的command时不会给用户显示提示或操作信息,但是-ok就会在有提示询问操作时给用户显示信息,直到用户做了选择时才继续执行。

 

常用的option值说明

-name 指定查找的内容是文件。

-type 指定查找的文件的类型,它有d,l,b,p,f,c等文件类型,d是查找目录,l是查找链接档,b是查找块文件,p是查找管道文件,f是普通文件,c是字符设备文件

-mtime,-ctime,atime都是指按时间查找,-mtime是文件的修改时间,-ctime是文件的创建时间,atime是后找开文件时间

-user是查找指定用户帐号的文件

-group是查找指定组帐号的文件

-nouser查找无用户帐号文件

-nogroup是查找无组帐号文件

 

下面举几个例子说明一下find的用法

(1)我想找出/etc目录下是passw开头的所有文件

   find /etc -name "passw*" 

这个例子中"*"号是正则匹配中的“所有”的意思

(2)我想找出/var/log目录下所有的前5天的.log文件

   find /var/log -name "*.log" -mtime +5

这个例子中"+5"是指5天以前的文件,如是查"-5"则是5天以内的文件

(3)我想找出/home目录下是"ygl"这个用户的文件

   find /home -user "ygl"

(4)我想找出/home目录下是"ygl"这个用户的所有的普通档的文件

   find /home -user "ygl" -type f

(5)我想找出/var/log目录下的所有的.log文件并查看它的详细信息

   find /var/log -name "*.log" -type f -exec ls -l {} \;

这个例子中用到了可选属性-exec用来执行ls命令,其中的-exec或者-ok的用法都要在它所执行的command后面接" {} \;"

(6)我想查找出在/etc中以passw开头的所有文件中有没有ygl这些内容的

   find /etc -name "passw*" -exec grep -in "ygl" {} \;

posted @ 2006-11-06 09:34 小小程序程序员混口饭吃 阅读(651) | 评论 (0)编辑 收藏
安装

查看软件xxx安装内容

*

dpkg -L xxx

查找软件

*

apt-cache search 正则表达式

查找文件属于哪个包

*

dpkg -S filename
apt-file search filename

查询软件xxx依赖哪些包

*

apt-cache depends xxx

查询软件xxx被哪些包依赖

*

apt-cache rdepends xxx

增加一个光盘源

*

sudo apt-cdrom add

系统升级

*

sudo apt-get update
sudo apt-get dist-upgrade

清除所以删除包的残余配置文件

*

dpkg -l |grep ^rc|awk '{print $2}' |tr ["\n"] [" "]|sudo xargs dpkg -P -

编译时缺少h文件的自动处理

*

sudo auto-apt run ./configure

查看安装软件时下载包的临时存放目录

*

ls /var/cache/apt/archives

系统

查看内核

*

uname -a

查看Ubuntu版本

*

cat /etc/issue

查看内核加载的模块

*

lsmod

查看PCI设备

*

lspci

查看USB设备

*

lsusb

查看网卡状态

*

sudo ethtool eth0

查看CPU信息

*

cat /proc/cpuinfo

显示当前硬件信息

*

lshw

硬盘

查看硬盘的分区

*

sudo fdisk -l

查看硬盘剩余空间

*

df -h
df -H

查看目录占用空间

*

du -hs 目录名

优盘没法卸载

*

sync
fuser -km /media/usbdisk

内存

查看当前的内存使用情况

*

free -l

进程

查看当前有哪些进程

*

ps -A

中止一个进程

*

kill 进程号(就是ps -A中的第一列的数字)
或者 killall 进程名

强制中止一个进程(在上面进程中止不成功的时候使用)

*

kill -9 进程号
或者 killall -9 进程名

查看当前进程的实时状况

*

top

查看进程打开的文件

*

lsof -p

ADSL

配置 ADSL

*

sudo pppoeconf

ADSL手工拨号

*

sudo pon dsl-provider

激活 ADSL

*

sudo /etc/ppp/pppoe_on_boot

断开 ADSL

*

sudo poff

查看拨号日志

*

sudo plog

网络

根据IP查网卡地址

*

arping IP地址

查看当前IP地址

*

sudo ifconfig eth0 |awk '/inet addr/ {split($2,x,":");print x[2]}'

查看当前外网的IP地址

*

w3m -no-cookie -dump www.ip138.com|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
w3m -no-cookie -dump ip.loveroot.com|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'

查看当前监听80端口的程序

*

lsof -i :80

查看当前网卡的物理地址

*

sudo arp -a | awk '{print $4}'
sudo ifconfig eth0 | head -1 | awk '{print $5}'

立即让网络支持nat

*

sudo echo 1 > /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -I POSTROUTING -j MASQUERADE

查看路由信息

*

netstat -rn
sudo route -n

手工增加删除一条路由

*

sudo route add -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1
sudo route del -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1

修改网卡MAC地址的方法

*

sudo ifconfig eth0 down #关闭网卡
sudo ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE #然后改地址
sudo ifconfig eth0 up #然后启动网卡

统计当前IP连接的个数

*

netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n
netstat -na|grep SYN|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n

统计当前20000个IP包中大于100个IP包的IP地址

*

tcpdump -tnn -c 20000 -i eth0 | awk -F "." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr | awk ' $1 > 100 '

屏蔽IPV6

*

echo "blacklist ipv6" | sudo tee /etc/modprobe.d/blacklist-ipv6

服务

添加一个服务

*

sudo update-rc.d 服务名 defaults 99

删除一个服务

*

sudo update-rc.d 服务名 remove

临时重启一个服务

*

/etc/init.d/服务名 restart

临时关闭一个服务

*

/etc/init.d/服务名 stop

临时启动一个服务

*

/etc/init.d/服务名 start

设置

配置默认Java使用哪个

*

sudo update-alternatives --config java

修改用户资料

*

sudo chfn userid

给apt设置代理

*

export http_proxy=http://xx.xx.xx.xx:xxx

修改系统登录信息

*

sudo vim /etc/motd

中文

转换文件名由GBK为UTF8

*

sudo apt-get install convmv
convmv -r -f cp936 -t utf8 --notest --nosmart *

转换文件内容由GBK为UTF8

*

iconv -f gbk -t utf8 $i > newfile

转换 mp3 标签编码

*

sudo apt-get install python-mutagen
find . -iname “*.mp3” -execdir mid3iconv -e GBK {} \;

文件

快速查找某个文件

*

whereis filename

*

find 目录 -name 文件名

查看文件类型

*

file filename

显示xxx文件倒数6行的内容

*

tail -n 6 xxx

查找包含xxx字符串的文件

*

grep -l -r xxx .

查找关于xxx的命令

*

apropos xxx
man -k xxx

通过ssh传输文件

*

scp -rp /path/filename username@remoteIP:/path #将本地文件拷贝到服务器上
scp -rp username@remoteIP:/path/filename /path #将远程文件从服务器下载到本地

查看某个文件被哪些应用程序读写

*

lsof 文件名

把所有文件的后辍由rm改为rmvb

*

rename 's/.rm$/.rmvb/' *

把所有文件名中的大写改为小写

*

rename 'tr/A-Z/a-z/' *

删除特殊文件名的文件,如文件名:--help.txt

*

rm -- --help.txt 或者 rm ./--help.txt

查看当前目录的子目录

*

ls -d */. 或 echo */.

压缩

解压缩 xxx.tar.gz

*

tar -zxvf xxx.tar.gz

解压缩 xxx.tar.bz2

*

tar -jxvf xxx.tar.bz2

压缩aaa bbb目录为xxx.tar.gz

*

tar -zcvf xxx.tar.gz aaa bbb

压缩aaa bbb目录为xxx.tar.bz2

*

tar -jcvf xxx.tar.bz2 aaa bbb

Nautilus

显示隐藏文件

*

Ctrl+h

显示地址栏

*

Ctrl+l

特殊 URI 地址

*

* computer:/// - 全部挂载的设备和网络
* network:/// - 浏览可用的网络
* burn:/// - 一个刻录 CDs/DVDs 的数据虚拟目录
* smb:/// - 可用的 windows/samba 网络资源
* x-nautilus-desktop:/// - 桌面项目和图标
* file:/// - 本地文件
* trash:/// - 本地回收站目录
* ftp:// - FTP 文件夹
* ssh:// - SSH 文件夹

查看已安装字体

*

在nautilus的地址栏里输入”fonts:///“,就可以查看本机所有的fonts

程序

详细显示程序的运行信息

*

strace -f -F -o outfile <cmd>

日期和时间

设置日期

*

#date -s mm/dd/yy

设置时间

*

#date -s HH:MM

将时间写入CMOS

*

hwclock --systohc

读取CMOS时间

*

hwclock --hctosys

控制台

不同控制台间切换

*

Ctrl + ALT + ←
Ctrl + ALT + →

指定控制台切换

*

Ctrl + ALT + Fn(n:1~7)

控制台下滚屏

*

SHIFT + pageUp/pageDown

控制台抓图

*

setterm -dump n(n:1~7)

数据库

mysql的数据库存放在地方

*

/var/lib/mysql

从mysql中导出和导入数据

*

mysqldump 数据库名 > 文件名 #导出数据库
mysqladmin create 数据库名 #建立数据库
mysql 数据库名 < 文件名 #导入数据库

忘了mysql的root口令怎么办

*

sudo /etc/init.d/mysql stop
sudo mysqld_safe --skip-grant-tables &
sudo mysqladmin -u user password 'newpassword''
sudo mysqladmin flush-privileges

修改mysql的root口令

*

sudo mysqladmin -uroot -p password '你的新密码'

其它

下载网站文档

*

wget -r -p -np -k http://www.21cn.com
· -r:在本机建立服务器端目录结构;
· -p: 下载显示HTML文件的所有图片;
· -np:只下载目标站点指定目录及其子目录的内容;
· -k: 转换非相对链接为相对链接。

删除Totem电影播放机的播放历史记录

*

rm ~/.recently-used

在桌面上显示计算机,HOME,回收站等图标

*

gconf-editor
找到apps-->nautilus-->desktop
勾选相应选项

Gaim声音设置

*

首选项->声音->声音方式,方式选“命令”,下面的声音命令填上“aplay %s”

清除apt-get cache

*

sudo apt-get clean
posted @ 2006-11-02 14:09 小小程序程序员混口饭吃 阅读(602) | 评论 (0)编辑 收藏

网上转载的,试过,确实能用,这是手动增加SWAP的一个很好的方式,建议在安装LINUX的时候开始就要建一个SWAP,最好是内存的2倍。
linux中增加swap分区文件的步骤方法:

1、检查当前的分区情况(使用free -m或cat /proc/swaps ):
 [root@db2 root]# free -m
              total       used       free     shared    buffers     cached
 Mem:          1006         84        922          0         11         38
 -/+ buffers/cache:         35        971
 Swap:            0          0          0
 [root@db2 root]#

2、增加交换分区文件及大小:
检查没有swap,下面就需要增加:
判定新交换文件的大小,将大小乘以1024来判定块的大小。例如,大小为64MB的交换文件的块大小为65536,在 shell 提示下以根用户身份键入以下命令,其中的 count 等于想要的块大小。

 [root@db2 root]# dd if=/dev/zero of=/home/swap bs=1024 count=1024000
 1024000+0 records in
 1024000+0 records out
 [root@db2 root]#

使用以下命令来设置交换文件:
 [root@db2 root]# mkswap /home/swap
 Setting up swapspace version 1, size = 1023996 KiB
 [root@db2 root]#

3、启用交换分区文件:
要立即启用交换文件而不是在引导时自动启用,使用以下命令:
 [root@db2 root]# swapon /home/swap

检查增加后的交换情况: 
 [root@db2 root]# free -m
              total       used       free     shared    buffers     cached
 Mem:          1006        994         12          0          4        929
 -/+ buffers/cache:         60        946
 Swap:          999          0        999
 [root@db2 root]#
 
要在引导时启用,编辑 /etc/fstab 文件来包含以下行(/home/swap               swap                    swap    defaults        0 0 ):
 [root@db2 root]# vi /etc/fstab
 LABEL=/                 /                       ext3    defaults        1 1       
 LABEL=/boot             /boot                   ext2    defaults        1 2      /home/swap               swap                    swap    defaults        0 0
        none                    /dev/pts                devpts  gid=5,mode=620  0 0     
        none                    /proc                   proc    defaults        0 0     
        none                    /dev/shm                tmpfs   defaults        0 0     
        LABEL=/usr              /usr                    ext3    defaults        1 2     
        /dev/sda5               swap                    swap    defaults        0 0     
        /dev/cdrom              /mnt/cdrom              iso9660 noauto,owner,kudzu,ro 0 0
        /dev/fd0                /mnt/floppy             auto    noauto,owner,kudzu 0 0  
        /home/swap               swap                    swap    defaults        0 0  
系统下次引导时,它就会启用新建的交换文件         
再次检查添加后的情况:
 [root@db2 oracledb]# free -m                                            
                     total       used       free     shared    buffers     cached
        Mem:          1006        979         27          0          6        917
        -/+ buffers/cache:         54        952                                
        Swap:          999          0        999                                
        [root@db2 oracledb]#     

posted @ 2006-11-02 13:49 小小程序程序员混口饭吃 阅读(4387) | 评论 (0)编辑 收藏
#!/bin/bash
#Copyright (c) 2005 ubuntu.org.cn
#License: GPLv2

#需要安装编码转换器
#sudo apt-get install recode

#mp3的地址
SOURCE="http://list.mp3.baidu.com/list/newhits.html"

#保存mp3的目录
SAVE="${HOME}/mp3100"

#下载重试次数
TRYCOUNT=2

#临时目录
TMP="/tmp/${USER}"

#创建下载目录
if [ ! -d "${SAVE}" ];then
    mkdir -p "${SAVE}"
fi

#创建临时下载目录
if [ ! -d "${TMP}" ];then
    mkdir -p "${TMP}"
fi

echo "开始下载百度最新100首歌曲列表"
wget -O ${TMP}/mp3.html ${SOURCE}
echo "下载百度最新100首歌曲列表完成。"

#转换网页编码
iconv -f gbk -t utf8 ${TMP}/mp3.html |\

grep "<a href=\"http://mp3.baidu.com/m" |\

#将mp3list.txt所有开头的空格去掉
sed -e 's/ *//' |\

#将mp3list.txt所有全角空格去掉
sed -e 's/ //g' |\

#将所有的回车符去掉
sed ':a;N;$!ba;s/\n/,/g' |\

#在td>,后面加上回车符,一行表示一个mp3文件。
sed -e 's/,<td/\n<td/g' |\
sed -e 's/td>,/td>\n/g' |\

#删除<td width="30%"> <td> </td> <td...FFFFFF"> <p> </p>
sed -e 's/<td width="30%">//g' |\
sed -e 's/<td>//g' |\
sed -e 's/<\/td>//g' |\
sed -e 's/<p>//g' |\
sed -e 's/<\/p>//g' |\
sed -e 's/<td.*FFFFFF">//g' |\

#删除</a>..."_blank">
sed -e 's/<\/a>.*_blank">/-/g' |\
sed -e 's/<\/a>.*_blank>/-/g' |\

#删除&amp;
sed -e 's/\&amp\;/\//g' >${TMP}/mp3list.txt

#得到:<a href="http://mp3.baidu.com/m?tn=baidump3&ct=134217728&lm=-1&li=2&word=Baby%20Baby%20tell%20me%20%CD%F5%D0%C4%C1%E8" target="_blank">Baby ,Baby tell me-王心凌</a>

#取得行号,循环
line=$(awk 'END{print NR}' ${TMP}/mp3list.txt)
i=1;
while((i<=line));do
   downed=0;
   mpline=`awk 'NR=='"$i"'' ${TMP}/mp3list.txt`
   url=`echo $mpline | sed -e 's/<a href="//g' | sed 's/\ target.*//g' | sed 's/"//g' | cat`
   name=`echo $mpline | sed -e 's/.*_blank">//g' | sed -e 's/.*_blank>//g' |\
        sed -e 's/<\/a>//g' | sed -e 's/\//-/g' | sed -e 's/:/-/g'  | sed -e 's/"/'\''/g'  | cat`
 
   #检查是否已经下载过这首歌,如果下载过,放弃
   if [ -e "${SAVE}/${name}.mp3" ] || [ -e "${SAVE}/${name}.wma" ]; then
      echo -e "\e[1;6m\e[1;31m发现 ${name} 下载过,忽略,继续下一首。\e[1;6m\e[00m"
      ((i++))
      continue;
   fi

   echo "开始通过 $url 下载 $name";
   wget -O ${TMP}/down.html $url
   echo "获取 $name 下载列表完成。";

   ##### 找出有效的歌曲下载地址并根据下载文件的大小从大至少排序 ###############
   #down.txt为有效的下载地址
   iconv -f gbk -t utf8 -c ${TMP}/down.html | grep "<td height=\"28\" class=\"d\">" |\
   sed -e 's/.*<a href="//g' | sed -e 's/" target=_blank>.*//g' |\
   sed '/mid/d' > ${TMP}/down.txt

   #size.txt为有效的下载文件大小
   iconv -f gbk -t utf8 -c ${TMP}/down.html | grep "M<\/td>" |\
   sed -e 's/<td class="t">//g' | sed -e 's/ M<\/td>//g' > ${TMP}/size.txt

   #down.txt与size.txt合并而在的down_size.txt文件中字段之间以" "作为分隔符
   paste -d ' ' ${TMP}/down.txt ${TMP}/size.txt > ${TMP}/down_size.txt

   #得到以下形式 (下载地址 文件大小)
   #http://wma2.7t7t.com/pycs/pycs/311/370247.Wma 1.2
   #http://snakelmq.hfxyd.com/milk/babybabytellme.mp3 3.2
   #http://bbsatt2.ccmove.com.cn/download/1280590/baby%20baby%20tell%20me%28PXC%D6%C6%D7%F7%29.mp3 0.3
   #http://vod.music165.com/music/song/new02/wxl_05.07.29/3.Wma 1.6
   #http://202.107.247.54/16/0406/94/3.wma 1.6

   #排序
   sort "+1nr" ${TMP}/down_size.txt > ${TMP}/down_size_sort.txt

   #去掉后面的尺寸
   sed 's/ .*$//' ${TMP}/down_size_sort.txt > ${TMP}/temp.txt
   
   ##### 析取出mp3 的下载地址或 wma的下载地址 ##############
   grep -i "mp3$" ${TMP}/temp.txt > ${TMP}/down_mp3.txt
   grep -i "wma$" ${TMP}/temp.txt > ${TMP}/down_wma.txt

   downline_mp3=$(awk 'END{print NR}' ${TMP}/down_mp3.txt);
   downline_wma=$(awk 'END{print NR}' ${TMP}/down_wma.txt);
   echo -e "\e[1;6m\e[1;31m发现 ${downline_mp3} 个名为 ${name}.mp3 下载地址。\e[1;6m\e[00m"
   echo -e "\e[1;6m\e[1;31m发现 ${downline_wma} 个名为 ${name}.wma 下载地址。\e[1;6m\e[00m"
   # 初始化计数器
   j=1;
   # 优先下载mp3格式的歌曲
   while((j<=downline_mp3)); do
      mp3=`awk 'NR=='"$j"'' ${TMP}/down_mp3.txt`
      echo -e "\e[1;6m\e[1;31m正在下载${name}.mp3\e[1;6m\e[00m"
      wget -c --tries=$TRYCOUNT $mp3 -O "${TMP}/${name}.mp3"
      if [ "$?" = 0 ]; then
         if [ `file -ib "${TMP}/${name}.mp3" | sed -e 's/\/.*//g'` = "audio" ]; then
            mv "${TMP}/${name}.mp3" "${SAVE}/${name}.mp3"
            downed=1;
            break;
         else
            echo -e "\e[1;6m\e[1;31m下载 ${name}.mp3 文件无效,正在删除重新下载\e[1;6m\e[00m"
            rm "${TMP}/${name}.mp3";
            ((j++))   
         fi
      else
         echo -e "\e[1;6m\e[1;31m下载 ${name}.mp3 文件无效,正在删除重新下载\e[1;6m\e[00m"
         rm "${TMP}/${name}.mp3";
         ((j++))
      fi
   done

   #如果下载成功继续下其余的歌
   #continue用于跳过循环体中的后续命令
   if [ "$downed" = 1 ] ; then
      ((i++))
      echo -e "\e[1;7m\e[1;41m下载 $name 成功\e[1;7m\e[00m"
      continue;
   fi

   # 如果没有mp3格式的则下载wma格式的歌
   j=1;
   while((j<=downline_wma)); do
      wma=`awk 'NR=='"$j"'' ${TMP}/down_wma.txt`
      echo -e "\e[1;6m\e[1;31m正在下载${name}.wma\e[1;6m\e[00m"
      wget -c --tries=$TRYCOUNT $wma -O "${TMP}/${name}.wma"
      if [ "$?" = 0 ]; then
         if [ `file -ib "${TMP}/${name}.wma" | sed -e 's/\/.*//g'` = "application" ]; then
            mv "${TMP}/${name}.wma" "${SAVE}/${name}.wma"
            downed=1;
            break;
         else
            echo -e "\e[1;6m\e[1;31m下载 ${name}.wma 文件无效,正在删除重新下载\e[1;6m\e[00m"
            rm "${TMP}/${name}.wma";
            ((j++))   
         fi
      else
          echo -e "\e[1;6m\e[1;31m下载 ${name}.wma 文件无效,正在删除重新下载\e[1;6m\e[00m"
          rm "${TMP}/${name}.wma";
          ((j++))
      fi
   done

   ((i++))
   if [ "$downed" = 1 ] ; then
      echo -e "\e[1;7m\e[1;41m下载 $name 成功\e[1;7m\e[00m"
   else
      echo -e "\e[1;7m\e[1;41m下载 $name 失败\e[1;7m\e[00m"
   fi
done
rm -fr ${TMP}
exit 0

原理是用wget下载下页面来,然后用SED来提取页面,提取到连接后下载

posted @ 2006-10-27 15:41 小小程序程序员混口饭吃 阅读(1155) | 评论 (1)编辑 收藏

(1) ubuntu 6.06

(2): 由于 ubuntu debian 的内核,所以要在 oracle 官方上下载 oracle-xe-universal_10.2.0.1-1.0_i386.deb

 

开始安装(先看下面要注意的问题,第四项)

 

1:dpkg –I oracle-xe-universal_10.2.0.1-1.0_i386.deb

 

出现一下问题

 

正在解压缩将用于更替的包文件 oracle-xe-universal ...

dpkg :依赖关系问题使得 oracle-xe-universal 的配置工作不能继续:

 oracle-xe-universal 依赖于 libaio (>= 0.3.96) | libaio1 (>= 0.3.96);然而:

  软件包 libaio还没有被安装。

  软件包 libaio1还没有被安装。

dpkg :处理 oracle-xe-universal (--install)时出错:

  依赖关系问题 - 仍未被配置

在处理时有错误发生:

 oracle-xe-universal

 

原来是libaio缺少,没有安装,我就下载下来,是个rpm,然后安装这个rpm

 

sudo apt-get libaio-0.3.96-7.i386.rpm

 

正在读取软件包列表... 完成

正在分析软件包的依赖关系树... 完成

E: 无法找到软件包 libaio-0.3.96-7.i386.rpm

 

真是郁闷反复试验都不行

 

 

放弃这样安装,到网上查找其他方案安装libaio

 

网上说采用apt-get -f install安装方式可能自动获取包

 

 

apt-get -f  install 果然可以日志如下

root@ubuntu:/home/oem# apt-get -f  install

正在读取软件包列表... 完成

正在分析软件包的依赖关系树... 完成

正在更正依赖关系... 完成

将会安装下列额外的软件包:

  libaio1

下列【新】软件包将被安装:

  libaio1

共升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 7 个软件未被升级。

1 个软件包没有被完全安装或卸载。

需要下载 5182B 的软件包。

解压缩后会消耗掉 61.4kB 的额外空间。

您希望继续执行吗?[Y/n]y

获取:1 http://mirror.lupaworld.com dapper/main libaio1 0.3.104-1ubuntu6 [5182B]下载 5182B,耗时 2s (2346B/s)

选中了曾被取消选择的软件包 libaio1

( 正在读取数据库 ... 系统当前总共安装有 76207 个文件和目录。)

正在解压缩 libaio1 ( .../libaio1_0.3.104-1ubuntu6_i386.deb) ...

正在设置 libaio1 (0.3.104-1ubuntu6) ...

 

正在设置 oracle-xe-universal (10.2.0.1-1.0) ...

Executing Post-install steps...

You must run '/etc/init.d/oracle-xe configure' as the root user to configure the database.

 

 

2

 

root@ubuntu:/home/oem#  /etc/init.d/oracle-xe configure

 

 

Oracle Database 10g Express Edition Configuration

-------------------------------------------------

This will configure on-boot properties of Oracle Database 10g Express

Edition.  The following questions will determine whether the database should

be starting upon system boot, the ports it will use, and the passwords that

will be used for database accounts.  Press <Enter> to accept the defaults.

Ctrl-C will abort.

 

Specify the HTTP port that will be used for Oracle Application Express [8080]:8080

 

Specify a port that will be used for the database listener [1521]:1521

 

Specify a password to be used for database accounts.  Note that the same

password will be used for SYS and SYSTEM.  Oracle recommends the use of

different passwords for each database account.  This can be done after

initial configuration:

Confirm the password:

 

Do you want Oracle Database 10g Express Edition to be started on boot (y/n) [y]:y

 

Starting Oracle Net Listener...Done

Configuring Database...

 

Starting Oracle Database 10g Express Edition Instance...Done

Installation Completed Successfully.

To access the Database Home Page go to "http://127.0.0.1:8080/apex"

 

 

  这就安装完了?真是不可思以,比9I快很多啊,总共花了10几分钟,中间的配置少了好多啊。

 

3 :访问数据

http://127.0.0.1:8080/apex

根据设置的密码没有问题,能够正确访问

 

 

4: 需要注意的问题:

在刚开始安装的时候可能出现一下问题

 

root@ubuntu:/home/oem# dpkg -i oracle-xe-universal_10.2.0.1-1.0_i386.deb

选中了曾被取消选择的软件包 oracle-xe-universal

( 正在读取数据库 ... 系统当前总共安装有 73613 个文件和目录。)

正在解压缩 oracle-xe-universal ( oracle-xe-universal_10.2.0.1-1.0_i386.deb) ...

This system does not meet the minimum requirements for swap space.  Based on

the amount of physical memory available on the system, Oracle Database 10g

Express Edition requires 750 MB of swap space. This system has 711 MB

of swap space.  Configure more swap space on the system and retry the installation.

dpkg :处理 oracle-xe-universal_10.2.0.1-1.0_i386.deb (--install)时出错:

  子进程·pre-installation script·返回了错误号·1

在处理时有错误发生:

 oracle-xe-universal_10.2.0.1-1.0_i386.deb

 

这个问题是由于SWAP分区不够的原因造成的,那就增加一个SWAP分区


 

1 :采用文件的方式增加swap分区

Dd if=/dev/zero of=/tmp/tmp.swap bs=1M count =100( 建立一个100M的文件)

mkswap /tmp/tmp.swap( 标识swap文件)

swapon /tmp/tmp.swap( 激活swap)

修改/etc/fstab文件增加一行

 

/tmp/tmp.swap swap swap defaluts 0 0

Swapon –s 查看当前的swap分区情况

发现已经有2SWAP分区了,空间这下子够了,可以继续安装了

 

2 :也可已采用直接增加SWAP方式(我没有采用这样的办法)

 

 

 

 

 

 

posted @ 2006-10-23 11:13 小小程序程序员混口饭吃 阅读(2170) | 评论 (0)编辑 收藏
昨天晚上,我们排着整齐的队伍来到电影院观看了电影《夜宴》。电影票好贵哟,不过老师说,能够看到章子怡阿姨光溜溜的背影,再贵也是值得的。

许多同学都不明白什么叫“夜宴”,我的语文功底比较好,于是就告诉他们“夜宴”其实就是“晚饭”的意思。只不过穷人的“晚饭”是“晚饭”,而有钱人的“晚饭”叫“夜宴”。

以前我总认为皇帝是天下最幸福的职业了,看了《夜宴》才知道,其实皇帝也很不开心。葛优叔叔演的皇帝是那么的爱章阿姨,经常给她做推油按摩,还关心她晚上睡觉“这么大的人还蹬被子”。葛叔叔的心肠很好,当他看到一个老爷爷被人用棍子打时,忍不住说“太残酷了”。最重要的是,葛叔叔为人非常正直,一些人劝他用假太子和契丹人交换,他却说:“我不学他!泱泱大国,诚信为本……”联想到这世界上还有那么多生产假冒伪劣、不诚信的商家,葛叔叔的情操是多么的高尚啊!中央电视台的3·15晚会应该请葛叔叔去倡导诚信宣言。


    可是章阿姨一点都不喜欢葛叔叔,一边给他下毒酒,一边还穿得很少和一个长得很帅的面具哥哥跳芭蕾舞。章阿姨当皇后之前一定是个发廊的洗头妹,因为她在皇宫里给太子睡洗头发时的指法非常专业。葛叔叔本来是可以叫卫兵杀章阿姨的,可他却毅然喝下了那杯毒酒,倒在阿姨的怀中,死的时候一直喃喃地说:“是复仇的火焰让你穿越了死亡之谷,抑或是你的忧郁打动了女人的心,让她们维系着你的生命?百般算计都不如一颗单纯的心……”看到这里,我们全班同学都忍不住流下了同情的眼泪。葛叔叔啊,你实在是太傻了啊!以你的才华,活到今天,再孬也能混成个汪国真,为什么要去迷恋那个并不爱你的洗头妹吗?


    说到这里,我很想谴责那些贩毒的坏人。电影中有个老爷爷,专门就是贩毒的,只要谁有钱,就可以到他那里买毒品,美丽的周迅姐姐就是被他卖出的摇头丸毒死的。老师告诉我们要“珍惜生命,远离毒品”,我们一定要牢牢记住,周姐姐的血是不能白流的!


    还有一点我很不明白,黄晓明哥哥和周迅姐姐之间的感情好奇怪哦!

老师教育我们,近亲之间不能耍朋友,不能结婚。可他们本来是兄妹,看起来却像是一对情侣,也许是他们不懂这些知识吧。从电影中,我又明白了一个道理,那就是学习不能偏科,不但要学好语文、数学、英语,还要学好《生理卫生》。不然就可能和黄哥哥一样,爱上自己的亲妹妹,一旦生下低能儿,后悔也就晚了。


    许多同学看完《夜宴》后都说没看懂,不懂葛叔叔手下部队那么多为什么还要自杀;不懂章阿姨武功那么高想杀葛叔叔随便趁晚上一起睡觉时动手就是,为什么还要买毒品下毒酒那么麻烦;特别没看懂的是究竟谁用飞刀把章阿姨杀死了的。我想了半天也没想明白,看来这个事情只有请警察叔叔帮忙了。公安局承诺了的,命案必破!才一顿晚饭的时间,就死了那么多人,他们不能不管吧?我相信,总有一天,章阿姨被害真相会大白于天下的!


    当然,看了《夜宴》最大的收获就是让我们认识到,古代封建社会治安真的太乱了,皇宫里都并不安全,更何况民间了。我们要珍惜身边来之不易的安定团结生活,好好学习,天天向上,长大了为建设和谐社会而贡献自己的力量。


来自http://forum.techweb.com.cn/viewthread.php?tid=40238
posted @ 2006-10-20 09:21 小小程序程序员混口饭吃 阅读(491) | 评论 (0)编辑 收藏

    
  先用gunzip   lnx_920_disk1.cpio.gz  
   
          cpio   -idmv   <   lnx_920_disk1.cpio
posted @ 2006-10-18 18:00 小小程序程序员混口饭吃 阅读(1476) | 评论 (0)编辑 收藏
1:买一度电用多个灯泡,电业局不管
2:买一吨水用多个水龙头,也没有人管
3:按一部电话多个分机也没有人管
4:一个人家里有3台电脑必须用安装3条宽待?

真是操!体制造成垄断!
posted @ 2006-10-18 09:13 小小程序程序员混口饭吃 阅读(830) | 评论 (4)编辑 收藏

1:门前number one

在上车之前一定要占据门前的一个位置,这需要技巧,事先看准车要停的位置
一般来说车停的位置是固定的,你看那个黄色的线的颜色就可以了,要是颜色黯淡了就证明
是车门的位置,因为人员来往频繁,把黄色踩掉了,提前上车更容易找到大位置

2:车头车尾和中间

一般来说车头车尾和中间的2个车门人数较少,这是我观察的结果,从第3个车门开始人很多,
到了中间人减少一些,所以选择上车的车厢位置很关键

3:观其色,看其年龄

在西直门上车后如果没有座位一定要选择一个年长一点的有座位的,你站在边上,
据我观察,在积水谭下车的人都是些40来岁的,可能这里的国有企业比较多把,年轻人一般
在东直门,朝阳门,建国门下,特别是穿着光鲜的人,一定不要站在他座位边上,一般来说他
在外企,外企的位置基本在东直门,朝阳门,建国门,所以你就要站着了。

4:研究行为学和心理学,抢座位也要讲理
观察下车人的行为,观察没有座位人的心里,不要跟老弱病残抢,当然要礼让了


5:以上几条是常用的,还有好多没有时间总结,总之我每天基本上都有座位

posted @ 2006-10-17 17:34 小小程序程序员混口饭吃 阅读(881) | 评论 (1)编辑 收藏
摘 要:介绍了Servlet多线程机制,通过一个实例并结合Java 的内存模型说明引起Servlet线程不安全的原因,给出了保证Servlet线程安全的三种解决方案,并说明三种方案在实际开发中的取舍。

  关键字:Servlet 线程安全 同步 Java内存模型 实例变量

  Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的安全性问题。然而,很多人编写Servlet/JSP程序时并没有注意到多线程安全性的问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫明其妙的问题。

  Servlet的多线程机制
 
  Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行,如图1所示。


图1 Servlet线程池

  这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构建的Web应用时如果不注意线程安全的问题,会使所写的Servlet程序有难以发现的错误。

  Servlet的线程安全问题

  Servlet的线程安全问题主要是由于实例变量使用不当而引起的,这里以一个现实的例子来说明。

Import javax.servlet. *;
Import javax.servlet.http. *;
Import java.io. *;
Public class Concurrent Test extends HttpServlet {PrintWriter output;
Public void service (HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {String username;
Response.setContentType ("text/html; charset=gb2312");
Username = request.getParameter ("username");
Output = response.getWriter ();
Try {Thread. sleep (5000); //为了突出并发问题,在这设置一个延时
} Catch (Interrupted Exception e){}
output.println("用户名:"+Username+"<BR>");
}
}

  该Servlet中定义了一个实例变量output,在service方法将其赋值为用户的输出。当一个用户访问该Servlet时,程序会正常的运行,但当多个用户并发访问时,就可能会出现其它用户的信息显示在另外一些用户的浏览器上的问题。这是一个严重的问题。为了突出并发问题,便于测试、观察,我们在回显用户信息时执行了一个延时的操作。假设已在web.xml配置文件中注册了该Servlet,现有两个用户a和b同时访问该Servlet(可以启动两个IE浏览器,或者在两台机器上同时访问),即同时在浏览器中输入:

  a: http://localhost: 8080/servlet/ConcurrentTest? Username=a

  b: http://localhost: 8080/servlet/ConcurrentTest? Username=b

  如果用户b比用户a回车的时间稍慢一点,将得到如图2所示的输出:


图2 a用户和b用户的浏览器输出

  从图2中可以看到,Web服务器启动了两个线程分别处理来自用户a和用户b的请求,但是在用户a的浏览器上却得到一个空白的屏幕,用户a的信息显示在用户b的浏览器上。该Servlet存在线程不安全问题。下面我们就从分析该实例的内存模型入手,观察不同时刻实例变量output的值来分析使该Servlet线程不安全的原因。

  Java的内存模型JMM(Java MemoryModel)JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。根据JMM,我们可以将论文中所讨论的Servlet实例的内存模型抽象为图3所示的模型。


图3 Servlet实例的JMM模型

  下面根据图3所示的内存模型,来分析当用户a和b的线程(简称为a线程、b线程)并发执行时,Servlet实例中所涉及变量的变化情况及线程的执行情况,如图4所示。

调度时刻 a线程b线程
T1访问Servlet页面 
T2  访问Servlet页面
T3 output=a的输出username=a休眠5000毫秒,让出CPU  
T4  output=b的输出(写回主存)username=b休眠5000毫秒,让出CPU
T5 在用户b的浏览器上输出a线程的username的值,a线程终止。 
T6 在用户b的浏览器上输出b线程的username的值,b线程终止。
                  图4 Servlet实例的线程调度情况

  从图4中可以清楚的看到,由于b线程对实例变量output的修改覆盖了a线程对实例变量output的修改,从而导致了用户a的信息显示在了用户b的浏览器上。如果在a线程执行输出语句时,b线程对output的修改还没有刷新到主存,那么将不会出现图2所示的输出结果,因此这只是一种偶然现象,但这更增加了程序潜在的危险性。
设计线程安全的Servlet

  通过上面的分析,我们知道了实例变量不正确的使用是造成Servlet线程不安全的主要原因。下面针对该问题给出了三种解决方案并对方案的选取给出了一些参考性的建议。

  1、实现 SingleThreadModel 接口

  该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要将前面的Concurrent Test类的类头定义更改为:

Public class Concurrent Test extends HttpServlet implements SingleThreadModel {
…………
}

  2、同步对共享数据的操作

  使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证线程的安全。同步后的代码如下:

…………
Public class Concurrent Test extends HttpServlet { …………
Username = request.getParameter ("username");
Synchronized (this){
Output = response.getWriter ();
Try {
Thread. Sleep (5000);
} Catch (Interrupted Exception e){}
output.println("用户名:"+Username+"<BR>");
}
}
}

  3、避免使用实例变量

  本实例中的线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。

  修正上面的Servlet代码,将实例变量改为局部变量实现同样的功能,代码如下:

……
Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse
Response) throws ServletException, IOException {
Print Writer output;
String username;
Response.setContentType ("text/html; charset=gb2312");
……
}
}

  对上面的三种方法进行测试,可以表明用它们都能设计出线程安全的Servlet程序。但是,如果一个Servlet实现了SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销。SingleThreadModel在Servlet2.4中已不再提倡使用;同样如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。另外为保证主存内容和线程的工作内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码;在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。

  小结

  Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。
posted @ 2006-09-19 11:43 小小程序程序员混口饭吃 阅读(549) | 评论 (0)编辑 收藏