2012年6月6日
#
- import Java.util.*;
- public class ShowDate {
- public static void main(String[] args) {
- Calendar calendar = new GregorianCalendar();
- Date trialTime = new Date();
- calendar.setTime(trialTime);
-
- System.out.println("ERA: " + calendar.get(Calendar.ERA));
- System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
- System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
- System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
- System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
- System.out.println("DATE: " + calendar.get(Calendar.DATE));
- System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
- System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
- System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
- System.out.println("DAY_OF_WEEK_IN_MONTH: " + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
- System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
- System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
- System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
- System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
- System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
- System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
- System.out.println("ZONE_OFFSET: " + (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
- System.out.println("DST_OFFSET: " + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000)));
- System.out.println("Current Time, with hour reset to 3");
- calendar.clear(Calendar.HOUR_OF_DAY);
- calendar.set(Calendar.HOUR, 3);
- System.out.println("ERA: " + calendar.get(Calendar.ERA));
- System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
- System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
- System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
- System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
- System.out.println("DATE: " + calendar.get(Calendar.DATE));
- System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
- System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
- System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
- System.out.println("DAY_OF_WEEK_IN_MONTH: " + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
Android SDK下载和更新失败的解决方法
最近刚换了电脑,开始搭建Android开发环境的时候,下载SDK总是会出现如下错误:
1.Failed to fetch URL http://dl-ssl.google.com/Android/repository/addons_list-1.xml.
据说dl-ssl.google.com在大陆被强了,伟大的天朝真是不让人活了,解决方法就是修改C:\Windows\System32\drivers\etc\hosts文件。添加一行:
1.74.125.237.1 dl-ssl.google.com
这里需要注意的是hosts文件是只读的,我们没有权限修改,需要我们将hosts文件复制到桌面或者其他地方,然后修改,代码如下:
1.# Copyright (c) 1993-2009 Microsoft Corp.
2.#
3.# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
4.#
5.# This file contains the mappings of IP addresses to host names. Each
6.# entry should be kept on an individual line. The IP address should
7.# be placed in the first column followed by the corresponding host name.
8.# The IP address and the host name should be separated by at least one
9.# space.
10.#
11.# Additionally, comments (such as these) may be inserted on individual
12.# lines or following the machine name denoted by a '#' symbol.
13.#
14.# For example:
15.#
16.# 102.54.94.97 rhino.acme.com # source server
17.# 38.25.63.10 x.acme.com # x client host
18.
19.# localhost name resolution is handled within DNS itself.
20.# 127.0.0.1 localhost
21.# ::1 localhost
22.//亲,就是增加这一句哦
23.74.125.237.1 dl-ssl.google.com
然后保存,复制修改后的hosts文件到C:\Windows\System32\drivers\etc 目录,替换文件就好!!!我们再次下载SDK的时候就会成功啦,如下图:
嘿嘿,大功告成啦!!!
PS:补充下,在mac或Linux中,hosts文件所在位置为/etc/hosts,可以使用sudo vim /etc/hosts来编辑。
Tomcat 6.0.35 的功能有些不同于Tomcat 6.0.20。我下载的Tomcat 6.0.35是免安装的,而以前使用的Tomcat 6.0.20是需要安装的,而且Tomcat 6.0.20 的安装密码,即进入Tomcat Manager 这个地方的密码是在安装的时候指定的,但是呢,Tomcat 6.0.35 由于是免安装的,所以就没有地方去指定密码了,当我们访问Tomcat 6.0.35 的Tomcat Manager的时候 ,输入以前默认的用户名:admin 密码为空,会发现出现了403 错误,即access deny 。调试了好久,最后终于找出原因了。根据403页面的提示,需要在tomcat的配置文件中(即conf/tomcat-users.xml)加入
<role rolename="manager-gui"/>
<user username="admin" password="" roles="manager-gui"/>
有一点必须注意,其中的rolename 必须是“manager-gui” ,更改成admin 或者 admin-gui,都不好用,而下面的username password是可以任意的,但是后面的roles 必须和上面role 中的rolename相同。
通过 jconsole查看tomcat运行情况的配置方法
——基于JDK1.5、Linux(Redhat5.5)、Tomcat6
由于项目的原因,需要使用jconsole对tomcat进行远程监控,结合网上的资料对配置方法进行了总结。
第一步、配置tomcat
打开%TOMCAT_HOME%/bin下的文件catalina.sh,搜索“JAVA_OPTS”找到下面这行:
if [ -z "$LOGGING_MANAGER" ]; then
JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
else
JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER"
fi
在每个“JAVA_OPTS”后边都添加以下标黄代码段,且在一行显示:
if [ -z "$LOGGING_MANAGER" ]; then JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.rmi.server.hostname=192.9.100.48 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"" else JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER -Djava.rmi.server.hostname=192.9.100.48 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"" fi |
其中-Djava.rmi.server.hostname项必须设置,否则远程连接会因为解析到127.0.0.1失败,该项的值就是你在windows客户端连接linux时的ip地址
-Dcom.sun.management.jmxremote.port="9004"项设置远程连接端口,不要与其他应用冲突
ssl和authenticate设置为false,如果需要安全,请不要false
第二步、重启tomcat
使用root身份登录系统,进入%TOMCAT_HOME%/bin目录下:
[root@test ~]#ps –ef |grep tomcat –-输入命令查看是否存在tomcat进程 [root@test ~]#./shutdown.sh--停止tomcat服务,如果无效使用kill命令杀掉进程 [root@test ~]#./startup.sh --启动tomcat服务 |
第三步、运行jconsole
进入JDK安装目录%JDK_HOME%/bin下,找到“jconsole.exe”,点击运行并选择【远程】选项卡:
在【主机名或ip】输入要远程监控的tomcat服务器地址
在【端口】输入上文设置的端口号:9004
【用户名、口令】为空,点击【连接】进入监控界面。
- import java.lang.management.MemoryUsage;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Formatter;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
-
- import javax.management.MBeanAttributeInfo;
- import javax.management.MBeanInfo;
- import javax.management.MBeanServerConnection;
- import javax.management.ObjectInstance;
- import javax.management.ObjectName;
- import javax.management.openmbean.CompositeDataSupport;
- import javax.management.remote.JMXConnector;
- import javax.management.remote.JMXConnectorFactory;
- import javax.management.remote.JMXServiceURL;
-
- public class test {
-
-
-
- public static void main(String[] args) {
- try {
-
- String jmxURL = "service:jmx:rmi:///jndi/rmi://192.168.1.126:10090/jmxrmi";//tomcat jmx url
- JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
-
- Map map = new HashMap();
- String[] credentials = new String[] { "monitorRole", "QED" };
- map.put("jmx.remote.credentials", credentials);
- JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map);
- MBeanServerConnection mbsc = connector.getMBeanServerConnection();
-
-
- ObjectName threadObjName = new ObjectName("Catalina:type=ThreadPool,name=http-8089");
- MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName);
-
- String attrName = "currentThreadCount";
- MBeanAttributeInfo[] mbAttributes = mbInfo.getAttributes();
- System.out.println("currentThreadCount:" + mbsc.getAttribute(threadObjName, attrName));
-
-
- for (int j = 0; j < mbsc.getDomains().length; j++) {
- System.out.println("###########" + mbsc.getDomains()[j]);
- }
- Set MBeanset = mbsc.queryMBeans(null, null);
- System.out.println("MBeanset.size() : " + MBeanset.size());
- Iterator MBeansetIterator = MBeanset.iterator();
- while (MBeansetIterator.hasNext()) {
- ObjectInstance objectInstance = (ObjectInstance) MBeansetIterator.next();
- ObjectName objectName = objectInstance.getObjectName();
- String canonicalName = objectName.getCanonicalName();
- System.out.println("canonicalName : " + canonicalName);
- if (canonicalName.equals("Catalina:host=localhost,type=Cluster")) {
-
- System.out.println("Cluster MBeans Details:");
- System.out.println("=========================================");
-
- String canonicalKeyPropList = objectName.getCanonicalKeyPropertyListString();
- }
- }
-
- ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime");
- System.out.println("厂商:" + (String) mbsc.getAttribute(runtimeObjName, "VmVendor"));
- System.out.println("程序:" + (String) mbsc.getAttribute(runtimeObjName, "VmName"));
- System.out.println("版本:" + (String) mbsc.getAttribute(runtimeObjName, "VmVersion"));
- Date starttime = new Date((Long) mbsc.getAttribute(runtimeObjName, "StartTime"));
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- System.out.println("启动时间:" + df.format(starttime));
-
- Long timespan = (Long) mbsc.getAttribute(runtimeObjName, "Uptime");
- System.out.println("连续工作时间:" + test.formatTimeSpan(timespan));
-
-
- ObjectName heapObjName = new ObjectName("java.lang:type=Memory");
- MemoryUsage heapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(heapObjName,
- "HeapMemoryUsage"));
- long maxMemory = heapMemoryUsage.getMax();
- long commitMemory = heapMemoryUsage.getCommitted();
- long usedMemory = heapMemoryUsage.getUsed();
- System.out.println("heap:" + (double) usedMemory * 100 / commitMemory + "%");
-
- MemoryUsage nonheapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(heapObjName,
- "NonHeapMemoryUsage"));
- long noncommitMemory = nonheapMemoryUsage.getCommitted();
- long nonusedMemory = heapMemoryUsage.getUsed();
- System.out.println("nonheap:" + (double) nonusedMemory * 100 / noncommitMemory + "%");
-
- ObjectName permObjName = new ObjectName("java.lang:type=MemoryPool,name=Perm Gen");
- MemoryUsage permGenUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(permObjName, "Usage"));
- long committed = permGenUsage.getCommitted();
- long used = heapMemoryUsage.getUsed();
- System.out.println("perm gen:" + (double) used * 100 / committed + "%");
-
-
- ObjectName managerObjName = new ObjectName("Catalina:type=Manager,*");
- Set<ObjectName> s = mbsc.queryNames(managerObjName, null);
- for (ObjectName obj : s) {
- System.out.println("应用名:" + obj.getKeyProperty("path"));
- ObjectName objname = new ObjectName(obj.getCanonicalName());
- System.out.println("最大会话数:" + mbsc.getAttribute(objname, "maxActiveSessions"));
- System.out.println("会话数:" + mbsc.getAttribute(objname, "activeSessions"));
- System.out.println("活动会话数:" + mbsc.getAttribute(objname, "sessionCounter"));
- }
-
-
- ObjectName threadpoolObjName = new ObjectName("Catalina:type=ThreadPool,*");
- Set<ObjectName> s2 = mbsc.queryNames(threadpoolObjName, null);
- for (ObjectName obj : s2) {
- System.out.println("端口名:" + obj.getKeyProperty("name"));
- ObjectName objname = new ObjectName(obj.getCanonicalName());
- System.out.println("最大线程数:" + mbsc.getAttribute(objname, "maxThreads"));
- System.out.println("当前线程数:" + mbsc.getAttribute(objname, "currentThreadCount"));
- System.out.println("繁忙线程数:" + mbsc.getAttribute(objname, "currentThreadsBusy"));
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static String formatTimeSpan(long span) {
- long minseconds = span % 1000;
-
- span = span / 1000;
- long seconds = span % 60;
-
- span = span / 60;
- long mins = span % 60;
-
- span = span / 60;
- long hours = span % 24;
-
- span = span / 24;
- long days = span;
- return (new Formatter()).format("%1$d天 %2$02d:%3$02d:%4$02d.%5$03d", days, hours, mins, seconds, minseconds)
- .toString();
- }
-
- }
- import java.util.Iterator;
- import java.util.Set;
- import javax.management.Attribute;
- import javax.management.MBeanInfo;
- import javax.management.MBeanServerConnection;
- import javax.management.MBeanServerInvocationHandler;
- import javax.management.ObjectInstance;
- import javax.management.ObjectName;
- import javax.management.remote.JMXConnector;
- import javax.management.remote.JMXConnectorFactory;
- import javax.management.remote.JMXServiceURL;
- public class Client {
- public static void main(String[] args) throws Exception {
- JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server");
- JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
- MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
- ObjectName mbeanName = new ObjectName("chengang:name=HelloWorld");
-
- System.out.println("Domains:---------------");
- String domains[] = mbsc.getDomains();
- for (int i = 0; i < domains.length; i++) {
- System.out.println("\tDomain[" + i + "] = " + domains[i]);
- }
-
- System.out.println("MBean count = " + mbsc.getMBeanCount());
-
- mbsc.setAttribute(mbeanName, new Attribute("Name", "PANDA"));
- System.out.println("Name = " + mbsc.getAttribute(mbeanName, "Name"));
-
- HelloMBean proxy = (HelloMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);
- proxy.printHello();
- proxy.printHello("Raymend");
-
- mbsc.invoke(mbeanName, "printHello", null, null);
- mbsc.invoke(mbeanName, "printHello", new Object[] { "熊猫烧香" }, new String[] { String.class.getName() });
-
- MBeanInfo info = mbsc.getMBeanInfo(mbeanName);
- System.out.println("Hello Class: " + info.getClassName());
- System.out.println("Hello Attriber:" + info.getAttributes()[0].getName());
- System.out.println("Hello Operation:" + info.getOperations()[0].getName());
-
- System.out.println("all ObjectName:---------------");
- Set set = mbsc.queryMBeans(null, null);
- for (Iterator it = set.iterator(); it.hasNext();) {
- ObjectInstance oi = (ObjectInstance) it.next();
- System.out.println("\t" + oi.getObjectName());
- }
-
- jmxc.close();
- }
- }
由于现在项目中用到了LinkedHashMap,并不是太熟悉就到网上搜了一下。
import
java.util.HashMap;
import
java.util.Iterator;
import
java.util.LinkedHashMap;
import
java.util.Map;
public
class TestLinkedHashMap {
public static
void main(String args[])
{
System.out.println( "*************************LinkedHashMap*************" );
Map<Integer,String> map = new LinkedHashMap<Integer,String>();
map.put( 6 , "apple" );
map.put( 3 , "banana" );
map.put( 2 , "pear" );
for (Iterator it = map.keySet().iterator();it.hasNext();)
{
Object key = it.next();
System.out.println( key+ "=" + map.get(key));
}
System.out.println( "*************************HashMap*************" );
Map<Integer,String> map1 = new HashMap<Integer,String>();
map1.put( 6 , "apple" );
map1.put( 3 , "banana" );
map1.put( 2 , "pear" );
for (Iterator it = map1.keySet().iterator();it.hasNext();)
{
Object key = it.next();
System.out.println( key+ "=" + map1.get(key));
}
}
}
|
运行结果如下:
*************************LinkedHashMap*************
6=apple
3=banana
2=pear
*************************HashMap**************************
2=pear
6=apple
3=banana
分析:LinkedHashmap 的特点是put进去的对象位置未发生变化,而HashMap会发生变化.
再普及下:
java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap
Hashtable LinkedHashMap 和TreeMap.
Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复。
Hashmap
是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。
HashMap最多只允许一条记录的键为Null;允许多条记录的值为
Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用
Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
Hashtable与
HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了
Hashtable在写入时会比较慢。
LinkedHashMap
是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比
LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator
遍历TreeMap时,得到的记录是排过序的。
一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap
是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap
可以实现,它还可以按读取顺序来排列.
HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为NULL,允许多条记录的值为NULL。
HashMap不支持线程同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致性。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。
Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入时会比较慢。
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。
在遍历的时候会比HashMap慢TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iterator遍历TreeMap时,得到的记录是排过序的。
记下来,很重要。
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
举例说明:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
package ths;
public class Thread1 implements Runnable {
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}
结果:
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
package ths;
public class Thread2 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2(); } }, "t2" );
t1.start();
t2.start();
}
}
结果:
t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
//修改Thread2.m4t2()方法:
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
//修改Thread2.m4t2()方法如下:
public synchronized void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
五、以上规则对其它对象锁同样适用:
package ths;
public class Thread3 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用对象锁
inner.m4t1();
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
t1.start();
t2.start();
}
}
结果:
尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0
现在在Inner.m4t2()前面加上synchronized:
private synchronized void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
结果:
尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。
t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
第二篇:
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能
执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行
状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有
一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)
。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成
员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为
synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可
以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供
了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机
制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
对synchronized(this)的一些理解
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线
程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized
(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)
同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个
object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用
http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html
java中synchronized用法
打个比方:一个object就像一个大房子,大门永远打开。房子里有 很多房间(也就是方法)。
这些房间有上锁的(synchronized方法), 和不上锁之分(普通方法)。房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间。
另外我把所有想调用该对象方法的线程比喻成想进入这房子某个 房间的人。所有的东西就这么多了,下面我们看看这些东西之间如何作用的。
在此我们先来明确一下我们的前提条件。该对象至少有一个synchronized方法,否则这个key还有啥意义。当然也就不会有我们的这个主题了。
一个人想进入某间上了锁的房间,他来到房子门口,看见钥匙在那儿(说明暂时还没有其他人要使用上锁的 房间)。于是他走上去拿到了钥匙
,并且按照自己 的计划使用那些房间。注意一点,他每次使用完一次上锁的房间后会马上把钥匙还回去。即使他要连续使用两间上锁的房间,
中间他也要把钥匙还回去,再取回来。
因此,普通情况下钥匙的使用原则是:“随用随借,用完即还。”
这时其他人可以不受限制的使用那些不上锁的房间,一个人用一间可以,两个人用一间也可以,没限制。但是如果当某个人想要进入上锁的房
间,他就要跑到大门口去看看了。有钥匙当然拿了就走,没有的话,就只能等了。
要是很多人在等这把钥匙,等钥匙还回来以后,谁会优先得到钥匙?Not guaranteed。象前面例子里那个想连续使用两个上锁房间的家伙,他
中间还钥匙的时候如果还有其他人在等钥匙,那么没有任何保证这家伙能再次拿到。 (JAVA规范在很多地方都明确说明不保证,象
Thread.sleep()休息后多久会返回运行,相同优先权的线程那个首先被执行,当要访问对象的锁被 释放后处于等待池的多个线程哪个会优先得
到,等等。我想最终的决定权是在JVM,之所以不保证,就是因为JVM在做出上述决定的时候,绝不是简简单单根据 一个条件来做出判断,而是
根据很多条。而由于判断条件太多,如果说出来可能会影响JAVA的推广,也可能是因为知识产权保护的原因吧。SUN给了个不保证 就混过去了
。无可厚非。但我相信这些不确定,并非完全不确定。因为计算机这东西本身就是按指令运行的。即使看起来很随机的现象,其实都是有规律
可寻。学过 计算机的都知道,计算机里随机数的学名是伪随机数,是人运用一定的方法写出来的,看上去随机罢了。另外,或许是因为要想弄
的确定太费事,也没多大意义,所 以不确定就不确定了吧。)
再来看看同步代码块。和同步方法有小小的不同。
1.从尺寸上讲,同步代码块比同步方法小。你可以把同步代码块看成是没上锁房间里的一块用带锁的屏风隔开的空间。
2.同步代码块还可以人为的指定获得某个其它对象的key。就像是指定用哪一把钥匙才能开这个屏风的锁,你可以用本房的钥匙;你也可以指定
用另一个房子的钥匙才能开,这样的话,你要跑到另一栋房子那儿把那个钥匙拿来,并用那个房子的钥匙来打开这个房子的带锁的屏风。
记住你获得的那另一栋房子的钥匙,并不影响其他人进入那栋房子没有锁的房间。
为什么要使用同步代码块呢?我想应该是这样的:首先对程序来讲同步的部分很影响运行效率,而一个方法通常是先创建一些局部变
量,再对这些变量做一些 操作,如运算,显示等等;而同步所覆盖的代码越多,对效率的影响就越严重。因此我们通常尽量缩小其影响范围。
如何做?同步代码块。我们只把一个方法中该同 步的地方同步,比如运算。
另外,同步代码块可以指定钥匙这一特点有个额外的好处,是可以在一定时期内霸占某个对象的key。还记得前面说过普通情况下钥
匙的使用原则吗。现在不是普通情况了。你所取得的那把钥匙不是永远不还,而是在退出同步代码块时才还。
还用前面那个想连续用两个上锁房间的家伙打比方。怎样才能在用完一间以后,继续使用另一间呢。用同步代码块吧。先创建另外
一个线程,做一个同步代码 块,把那个代码块的锁指向这个房子的钥匙。然后启动那个线程。只要你能在进入那个代码块时抓到这房子的钥匙
,你就可以一直保留到退出那个代码块。也就是说 你甚至可以对本房内所有上锁的房间遍历,甚至再sleep(10*60*1000),而房门口却还有
1000个线程在等这把钥匙呢。很过瘾吧。
在此对sleep()方法和钥匙的关联性讲一下。一个线程在拿到key后,且没有完成同步的内容时,如果被强制sleep()了,那key还一
直在 它那儿。直到它再次运行,做完所有同步内容,才会归还key。记住,那家伙只是干活干累了,去休息一下,他并没干完他要干的事。为
了避免别人进入那个房间 把里面搞的一团糟,即使在睡觉的时候他也要把那唯一的钥匙戴在身上。
最后,也许有人会问,为什么要一把钥匙通开,而不是一个钥匙一个门呢?我想这纯粹是因为复杂性问题。一个钥匙一个门当然更
安全,但是会牵扯好多问题。钥匙 的产生,保管,获得,归还等等。其复杂性有可能随同步方法的增加呈几何级数增加,严重影响效率。这也
算是一个权衡的问题吧。为了增加一点点安全性,导致效 率大大降低,是多么不可取啊。
synchronized的一个简单例子
public class TextThread {
public static void main(String[] args) {
TxtThread tt = new TxtThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class TxtThread implements Runnable {
int num = 100;
String str = new String();
public void run() {
synchronized (str) {
while (num > 0) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.getMessage();
}
System.out.println(Thread.currentThread().getName()
+ "this is " + num--);
}
}
}
}
上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)
Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如
何?――还得对synchronized关键字的作用进行深入了解才可定论。
总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,
synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
在进一步阐述之前,我们需要明确几点:
A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其
他线程的对象访问。
B.每个对象只有一个锁(lock)与之相关联。
C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
接着来讨论synchronized用到不同地方对代码产生的影响:
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。
1. 把synchronized当作函数修饰符时,示例代码如下:
Public synchronized void methodAAA()
{
//….
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中
执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了
synchronized关键字的方法。
上边的示例代码等同于如下代码:
public void methodAAA()
{
synchronized (this) // (1)
{
//…..
}
}
(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个
拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造
成数据混乱:(
2.同步块,示例代码如下:
public void method3(SomeObject so)
{
synchronized(so)
{
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明
确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:
class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance变量
Public void methodA()
{
synchronized(lock) { //… }
}
//…..
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock
= new Object()则需要7行操作码。
3.将synchronized作用于static 函数,示例代码如下:
Class Foo
{
public synchronized static void methodAAA() // 同步的static 函数
{
//….
}
public void methodBBB()
{
synchronized(Foo.class) // class literal(类名称字面常量)
}
}
代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这
个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的
目的。P1指的是由Foo类产生的对象。
可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj
在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。
小结如下:
搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。
还有一些技巧可以让我们对共享资源的同步访问更加安全:
1. 定义private 的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以
绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。
2. 如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象
的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并
且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了
MyEclipse的基础配置:
1. 先安装MyEclipse,安装MyEclipse7.5需要VPN代理,安装过程大概持续10-15分钟,使用VPN测试帐号即可
2. 进行MyEclipse的配置,
从菜单栏中进入“Windows --> Preferences”
3. 先要进行JDK的配置,
在左侧栏中选择“Java --> Installed JREs”,
按“Add”按钮进行添加
4. 在弹出的“Add JRE”画面中,选择JRE的目录,
就是选择你所在的JDK的目录,我的为:C:\Program Files\Java\jre6
在JRE名称一栏中,填下想取的名称,我这里叫“HiJackson's JRE”,
然后“OK”确定
5. 返回到设置框中,将刚刚配置的JRE选中
6. 将Tomcat Server设为可用,并设置Tomcat的安装目录
7. 在Tomcat的JDK中选择刚刚配置的JDK
8. 配置完成了,三个地方可以启动它的服务,根据自己的喜好吧~~~
优化MyEclipse:
1、去除不需要加载的模块
一个系统20%的功能往往能够满足80%的需求,MyEclipse也不例外,我们在大多数时候只需要20%的系统功能,所以可以将一些不使用的模块禁止 加载启动。通过Windows - Preferences打开配置窗口,依次选择左侧的General - Startup and Shutdown,这个时候在右侧就显示出了Eclipse启动时加载的模块,可以根据自己的实际情况去除一些模块。
windows–>perferences–>general–>startup and shutdown
关掉没用的启动项:
WTP :一个跟myeclipse差不多的东西,主要差别是 WTP 是免费的,如果使用myeclipse,这个可以取消
Mylyn:组队任务管理工具,类似于 CVS ,以任务为单位管理项目进度,没用到的可以取消
Derby:一种保存成 jar 形式的数据库,我没用到,取消
一大排以 MyEclipse EASIE 打头的启动项:myeclipse 支持的服务器,只选自己用的,其他取消,比如我只选了tomcat6.x
2、取消MyEclipse在启动时自动验证项目配置文件
默认情况下MyEclipse在启动的时候会自动验证每个项目的配置文件,这是一个非常耗时的过程,
可以在Preferences窗口依次选择 MyEclipse Enterprise Workbench - Validation,然后在右侧的Validator列表中只保留 Manual 项就可以了(Manual全部勾选,Bulid项只留下第一项)。
如果需要验证的时候只需要选中文件,然后右键选择 MyEclipse - Run Validation就可以了。
windows–>perferences–>myeclipse–>validation
把 除了manual 下面的全部点掉,build下只留 classpath dependency Validator
手工验证方法:
在要验证的文件上,单击鼠标右键–>myeclipse–>run validation
3、去掉拼写检查(如果你觉的有用可以不去)
拼写检查会给我们带来不少的麻烦,我们的方法命名都会是单词的缩写,他也会提示有错,所以最好去掉,没有多大的用处:
windows–>perferences–>general–>validation->editors->Text Editors->spelling
myeclipse 打开 jsp 的默认编辑器不好,会同时打开预览
windows–>perferences–>general–>editors->file associations,
把默认改成 MyEclipse JSP Editor()
原默认的jsp编辑器是 MyEclipse Visual JSP Designer,顾名思义,此编译器是jsp可视化编辑器,对于初学者有很多的帮助,
但修改此项的默认编辑器其实可以提高启动速度)
4、关闭自动更新
如果是myeclipse7.5:
(1)关掉maven自动更新:
window-preferences-MyEclipse Enterprise Workbench-Maven4MyEclipse-Maven,
关闭所有Download和Update开头的选项,共四项(去掉前面的勾)
(2)关闭更新调度:window –> preferences –> General –> Startup and Shutdown –> Automatic Updates Scheduler(去掉前面的勾)
(3)window –> preferences –>Myeclipse Dashboard,关闭Show……on start
5、加大JVM的非堆内存
打开 myeclipse.ini
-startup
../Common\plugins\org.eclipse.equinox.launcher_1.0.101.R34x_v20081125.jar
--launcher.library
../Common\plugins\org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731
-clean
-configuration
configuration
-vm
C:\Users\lenovo\AppData\Local\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\bin\client\jvm.dll
-vmargs
-Xmx384m
-XX:MaxPermSize=384m
-XX:ReservedCodeCacheSize=96m
以上是我的myeclipse.ini,需要修改是-Xmx,-XX:MaxPermSize,-XX:ReservedCodeCacheSize,
将这三项的值调大,但并不是越大越好,曾经在相同的条件下做过测试(内存2GB),-Xmx,-XX:MaxPermSize的值为384m时比512m时要快(视具体的计算机而定),
-Xmx,-XX:MaxPermSize的值设为同样大小且两者之和不能超出你的计算机本身的内存大小
6、window-preferences-MyEclipse Enterprise Workbench-Maven4MyEclipse-Maven,将Maven JDK改为电脑上安装的JDK,即不使用myeclipse提高的JDK
登记add按钮,选择你的电脑上的JDK即可(注意:不是JRE,我的值为:Java6.014)
7、window-preferences-MyEclipse Enterprise Workbench-Matisse4Myeclipse/Swing,将Design-time information(dt.jar) location 改用电脑安装的JDK的dt.jar
(即不使用myeclipse提供的dt.jar,我的值为:C:\Java6.014\lib\dt.jar)
经过以上的优化,myeclipse的启动时间可以减少2/3,Tomcat的启动速度可以减少1/2(视具体情况而定),
特别6,7两项的优化效果最明显,
如果只进行前5项,优化的效果有限,短期内确实可以提高启动速度,但是大概半个月后又会变的很慢(具体原因不明)
另外,使用myeclipse一段时间后,就会产生很多项目,即使这些项目是处于关闭状态,myecliose在启动时也会加载这些项目,这个过程会花费很多时间,所以,建议将不用的项目都delete掉,用的时候再import
在用[MyEclipse] 写代码很容易卡死机,尤其是在对JSP文件的﹤%%﹥之间写代码的时候,只要一弹出智能提示就立刻卡死,程序失去响应,我以为是MyEclipse版本的问题,结果换了6.0版-﹥6.5版-﹥7.0版全都一样,难道是我机子的问题?可是还原系统后用还是一样的结果。
百度一下你就知道,但是百度了N下才找到了一些门路,搜索也讲究技巧,换了N个[关键字] 组合才搜出来。说是MyEclipse在智能提示的时候自动访问网络上sun公司的最新API文档,只要关闭掉网络连接就可以了。我试了试断开网络然后在用MyEclipse写代码,结果还真的搞定了。可是,我总不能因为个这就不上网了吧,继续接着百度,找到了两全其美的解决方法。
在自己创建的工程名上右键,选择Properties--﹥在打开的窗口中点击Java Build Path--﹥单击Libraries选项卡,找到如图中标记2所示的地方--﹥选择右边的Remove更改成如标记1所示的样子--﹥点击OK。
1、不常用的切换函数$("p").toggle();当点击切换按钮时,隐藏元素为P行和显示P行;
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$("p").toggle();
});
});
</script>
</head>
<body>
<button type="button">切换</button>
<p>This is a paragraph with little content.</p>
<p>This is another small paragraph.</p>
</body>
</html>
2、append() 函数向所匹配的 HTML 元素内部追加内容$(selector).append(content);
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$("p").append(" <b>W3School</b>.");
});
});
</script>
</head>
<body>
<h2>This is a heading</h2>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<button type="button">请点击这里</button>
</body>
</html>
类似的还有:
$(selector).html(content) 改变被选元素的(内部)HTML
$(selector).append(content) 向被选元素的(内部)HTML 追加内容
$(selector).prepend(content) 向被选元素的(内部)HTML “预置”(Prepend)内容
$(selector).after(content) 在被选元素之后添加 HTML
$(selector).before(content) 在被选元素之前添加 HTML
3、css操作:函数 css({properties}) 同时为所有匹配元素的一系列 CSS 属性设置值:
$(selector).css({properties})
$("p").css({"background-color":"red","font-size":"200%"});
jQuery 拥有两种用于尺寸操作的重要函数:
- $(selector).height(value)
- $(selector).width(value)
总结如:
$(selector).css(name,value) 为匹配元素设置样式属性的值
$(selector).css({properties}) 为匹配元素设置多个样式属性
$(selector).css(name) 获得第一个匹配元素的样式属性值
$(selector).height(value) 设置匹配元素的高度
$(selector).width(value) 设置匹配元素的宽度
4、AJAX:
jQuery AJAX 请求
$(selector).load(url,data,callback) 把远程数据加载到被选的元素中
$.ajax(options) 把远程数据加载到 XMLHttpRequest 对象中
$.get(url,data,callback,type) 使用 HTTP GET 来加载远程数据
$.post(url,data,callback,type) 使用 HTTP POST 来加载远程数据
$.getJSON(url,data,callback) 使用 HTTP GET 来加载远程 JSON 数据
$.getScript(url,callback) 加载并执行远程的 JavaScript 文件
(url) 被加载的数据的 URL(地址)
(data) 发送到服务器的数据的键/值对象
(callback) 当数据被加载时,所执行的函数
(type) 被返回的数据的类型 (html,xml,json,jasonp,script,text)
(options) 完整 AJAX 请求的所有键/值对选项
略。。。
由于开发经验较少,数据量较大(千万级,日有40万条数据左右),导致这个分页jsp页面做的效率非常低,通过一系列的优化后,效果明显得到了提高,记录一下笔记:
1、分页获取的list对象集合由于没有预料到数据量的大小,是直接一次性读取然后展示到前台的,导致查询展示效率非常低:
更改SQL语句,改为按照当前需要展示的数据行数,通过SQL的ROWNUM来进行控制查询的数据量大小,(插入数据时,打开一个数据库连接即一次性插入100条数据(可以配置的模式)):
SELECT BRAS_ADDRESS, APPLYTIMES, ALLFAILTIMES,SUCCESSRATE, RN
FROM
(SELECT BRAS_ADDRESS, APPLYTIMES, ALLFAILTIMES,SUCCESSRATE, ROWNUM AS RN
FROM
(SELECT BRAS_ADDRESS, APPLYTIMES, ALLFAILTIMES,1-ALLFAILTIMES/DECODE(APPLYTIMES,0,1,APPLYTIMES) AS SUCCESSRATE
FROM
(SELECT BRAS_ADDRESS,
SUM(DECODE(AUTNCOUNTTYPE,'REQ_CHALLENGE',APPLYTIMES,0)) AS APPLYTIMES,
SUM(DECODE(AUTNCOUNTTYPE,'ACK_CHALLENGE',APPLYTIMES,'ACK_AUTH',APPLYTIMES,'REQ_LOGOUT',APPLYTIMES,0)) AS ALLFAILTIMES
FROM T_BRAS_XXXX
WHERE READTIME between TO_DATE('2012-06-01 00:00:00','yyyy-MM-dd HH24:mi:ss')
and TO_DATE('2012-06-12 23:59:59','yyyy-MM-dd HH24:mi:ss')
GROUP BY BRAS_ADDRESS
)
ORDER BY SUCCESSRATE
)
WHERE ROWNUM <= 180
)
WHERE RN > 165 2、建立索引,建立索引的字段不能使用函数避免索引失效;
3、建立分区表,将间隔5天的数据放在一个表中:
----------------------删除原表,新建分区表
--删除表
drop table T_BRAS_XXXX;
commit;
--创建分区表:利用Oracle11g INTERVAL进行分区的方法
create table T_BRAS_XXXX
(
BRAS_XXXX_ID integer NOT NULL PRIMARY KEY,
BRAS_XXXX VARCHAR2(64),
AUTNCOUNTTYPE VARCHAR2(50),
SUCCESSTIMES NUMBER,
APPLYTIMES NUMBER,
INTERVALTIME NUMBER,
UPDATETIME DATE DEFAULT SYSDATE,
READTIME DATE
)
PARTITION BY RANGE (READTIME)
INTERVAL (NUMTODSINTERVAL(5,'day'))
(
PARTITION T_BRAS_XXXX_PART01 VALUES LESS THAN (TO_DATE('2012-07-01 00:00:00','yyyy-MM-dd HH24:mi:ss'))
)
--保留原来创建的BRAS_XXXX_ID自增序列
--创建索引
create index idx_t_bras_XXXX on t_bras_XXXX(readtime,bras_address);
commit;
--查看分区是否成功:
select table_name,partition_name from user_tab_partitions where table_name='T_BRAS_XXXX';
CREATE OR REPLACE PROCEDURE "LARGEDATA_INSERT" (ip_table_name in varchar2, --目标表
ip_table_column in varchar2, --目标字段
ip_table_select in varchar2, --SELECT 查询语句
return_result out number --返回的结果1,表示成功,0表示失败
) as
--适合大数据量的插入模板 create Templates by chenzhoumin 20110614
runTime number;--运行总次数
i number;--当前行数
amount number;--总行数
s_sql varchar2(10000);--SQL语句
e_sql varchar2(10000);--执行SQL语句
countNumber number;--一次插入的数据量
begin
--set serveroutput on size 20000000000000
countNumber := 10000;
return_result := 0; --开始初始化为0
--核必逻辑内容,可根据具体的业务逻辑来定义,统计数据总行数
s_sql := 'select count(1) from (' || ip_table_select || ')';
execute immediate s_sql
into amount;
--每100万提交一次
runTime := amount mod countNumber;
if (runTime > 0) then
runTime := 1 + trunc(amount / countNumber);
end if;
if (runTime = 0) then
runTime := 0 + trunc(amount / countNumber);
end if;
FOR i IN 1 .. runTime LOOP
e_sql := 'insert into '||ip_table_name ||'
('||ip_table_column ||')
select '|| ip_table_column ||'
from
(select selectSec.*, rownum rownumType
from ('|| ip_table_select ||') selectSec
WHERE ROWNUM <= '|| i * countNumber ||')
WHERE rownumType > '||(i - 1) * countNumber;
dbms_output.enable(99999999999999);
dbms_output.put_line(e_sql);
execute immediate e_sql;
--提交
commit;
END LOOP;
return_result := 1;
return;
exception
when others then
return_result := 0;
raise;
dbms_output.enable(99999999999999);
dbms_output.put_line('结束');
return;
end;
以上测试通过。
ORACLE数据库空间不足,会发生登录出错,数据无法插入等错误发生,可以根据实际错误代码查询原因,不过更多是平时多看看数据库空间是否足够;
解决办法有两个:
1、使用linux命令或者工具增加空间或者增加硬盘,没有实际操作过;
2、给oracel数据库增加系统表空间和临时表空间,记录下操作方法:
如果临时表空间或者SYSTEM表空间不足,可以进行新增数据文件到其它盘符(增加opt盘符目录):
select ts#, name from v$datafile;--查看当前的表空间状况
select * from database_properties where property_name='DEFAULT_TEMP_TABLESPACE';--查看默认的临时文件
create temporary tablespace temp2 tempfile '/opt/oracle/oracle_tmp/temp02.dbf' size 5000M autoextend on next 100M; --新增临时文件
alter database default temporary tablespace "TEMP2"; --修改默认临时文件设置
alter database tempfile '/home/oracle/oracle/oradata/portal/temp01.dbf' autoextend off; --关闭原来的临时文件自增长
增加系统表空间:
alter tablespace SYSTEM add datafile '/opt/oracle/oracle_tmp/system02.dbf' size 500M autoextend on next 5M;
如果startup数据库时,提示:prifile文件找不到,可以从一个$ORACLE_BASE/admin/portal/pfile目录下拷贝内容过去就可以(注意文件命名和原来使用的保持一样,只是内容不同):
当前正在使用的pfile:startup force pfile='/home/oracle/oracle/product/11.0.1/db_1/dbs/initportal.ora';
拷贝:cp $ORACLE_BASE/admin/portal/pfile/init.ora.452011185827 /home/oracle/oracle/product/11.0.1/db_1/dbs/spfileportal.ora
oracle 临时表空间的增删改查
1、查看临时表空间 (dba_temp_files视图)(v_$tempfile视图)
select tablespace_name,file_name,bytes/1024/1024 file_size,autoextensible from dba_temp_files;
select status,enabled, name, bytes/1024/1024 file_size from v_$tempfile;--sys用户查看
2、缩小临时表空间大小
alter database tempfile 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\TELEMT\TEMP01.DBF' resize 100M;
3、扩展临时表空间:
方法一、增大临时文件大小:
SQL> alter database tempfile ‘/u01/app/oracle/oradata/orcl/temp01.dbf’ resize 100m;
方法二、将临时数据文件设为自动扩展:
SQL> alter database tempfile ‘/u01/app/oracle/oradata/orcl/temp01.dbf’ autoextend on next 5m maxsize unlimited;
方法三、向临时表空间中添加数据文件:
SQL> alter tablespace temp add tempfile ‘/u01/app/oracle/oradata/orcl/temp02.dbf’ size 100m;
4、创建临时表空间:
SQL> create temporary tablespace temp1 tempfile ‘/u01/app/oracle/oradata/orcl/temp11.dbf’ size 10M;
5、更改系统的默认临时表空间:
--查询默认临时表空间
select * from database_properties where property_name='DEFAULT_TEMP_TABLESPACE';
--修改默认临时表空间
alter database default temporary tablespace temp1;
所有用户的默认临时表空间都将切换为新的临时表空间:
select username,temporary_tablespace,default_ from dba_users;
--更改某一用户的临时表空间:
alter user scott temporary tablespace temp;
6、删除临时表空间
删除临时表空间的一个数据文件:
SQL> alter database tempfile ‘/u01/app/oracle/oradata/orcl/temp02.dbf’ drop;
删除临时表空间(彻底删除):
SQL> drop tablespace temp1 including contents and datafiles cascade constraints;
7、查看临时表空间的使用情况(GV_$TEMP_SPACE_HEADER视图必须在sys用户下才能查询)
GV_$TEMP_SPACE_HEADER视图记录了临时表空间的使用大小与未使用的大小
dba_temp_files视图的bytes字段记录的是临时表空间的总大小
SELECT temp_used.tablespace_name,
total - used as "Free",
total as "Total",
round(nvl(total - used, 0) * 100 / total, 3) "Free percent"
FROM (SELECT tablespace_name, SUM(bytes_used) / 1024 / 1024 used
FROM GV_$TEMP_SPACE_HEADER
GROUP BY tablespace_name) temp_used,
(SELECT tablespace_name, SUM(bytes) / 1024 / 1024 total
FROM dba_temp_files
GROUP BY tablespace_name) temp_total
WHERE temp_used.tablespace_name = temp_total.tablespace_name
8、查找消耗资源比较的sql语句
Select se.username,
se.sid,
su.extents,
su.blocks * to_number(rtrim(p.value)) as Space,
tablespace,
segtype,
sql_text
from v$sort_usage su, v$parameter p, v$session se, v$sql s
where p.name = 'db_block_size'
and su.session_addr = se.saddr
and s.hash_value = su.sqlhash
and s.address = su.sqladdr
order by se.username, se.sid
9、查看当前临时表空间使用大小与正在占用临时表空间的sql语句
select sess.SID, segtype, blocks * 8 / 1000 "MB", sql_text
from v$sort_usage sort, v$session sess, v$sql sql
where sort.SESSION_ADDR = sess.SADDR
and sql.ADDRESS = sess.SQL_ADDRESS
order by blocks desc;
10、临时表空间组介绍
1)创建临时表空间组:
create temporary tablespace tempts1 tempfile '/home/oracle/temp1_02.dbf' size 2M tablespace group group1;
create temporary tablespace tempts2 tempfile '/home/oracle/temp2_02.dbf' size 2M tablespace group group2;
2)查询临时表空间组:dba_tablespace_groups视图
select * from dba_tablespace_groups;
GROUP_NAME TABLESPACE_NAME
------------------------------ ------------------------------
GROUP1 TEMPTS1
GROUP2 TEMPTS2
3)将表空间从一个临时表空间组移动到另外一个临时表空间组:
alter tablespace tempts1 tablespace group GROUP2 ;
select * from dba_tablespace_groups;
GROUP_NAME TABLESPACE_NAME
------------------------------ ------------------------------
GROUP2 TEMPTS1
GROUP2 TEMPTS2
4)把临时表空间组指定给用户
alter user scott temporary tablespace GROUP2;
5)在数据库级设置临时表空间
alter database <db_name> default temporary tablespace GROUP2;
6)删除临时表空间组 (删除组成临时表空间组的所有临时表空间)
drop tablespace tempts1 including contents and datafiles;
select * from dba_tablespace_groups;
GROUP_NAME TABLESPACE_NAME
------------------------------ ------------------------------
GROUP2 TEMPTS2
drop tablespace tempts2 including contents and datafiles;
select * from dba_tablespace_groups;
GROUP_NAME TABLESPACE_NAME
11、对临时表空间进行shrink(11g新增的功能)
--将temp表空间收缩为20M
alter tablespace temp shrink space keep 20M;
--自动将表空间的临时文件缩小到最小可能的大小
ALTER TABLESPACE temp SHRINK TEMPFILE ’/u02/oracle/data/lmtemp02.dbf’;
临时表空间作用
Oracle临时表空间主要用来做查询和存放一些缓冲区数据。临时表空间消耗的主要原因是需要对查询的中间结果进行排序。
重启数据库可以释放临时表空间,如果不能重启实例,而一直保持问题sql语句的执行,temp表空间会一直增长。直到耗尽硬盘空间。
网上有人猜测在磁盘空间的分配上,oracle使用的是贪心算法,如果上次磁盘空间消耗达到1GB,那么临时表空间就是1GB。
也就是说当前临时表空间文件的大小是历史上使用临时表空间最大的大小。
临时表空间的主要作用:
索引create或rebuild;
Order by 或 group by;
Distinct 操作;
Union 或 intersect 或 minus;
Sort-merge joins;
analyze.
JQuery中的select事件是change事件,在js中使用的是onchange事件:
<script src="jquery.min.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
$('#mySelect').change(function(){
alert($(this).children('option:selected').val());
var p1=$(this).children('option:selected').val();//这就是selected的值
var p2=$('#param2').val();//获取本页面其他标签的值
window.location.href="xx.php?param1="+p1+"¶m2="+p2+"";//页面跳转并传参
})
})
</script>
<select id="mySelect">
<option value="1">one</option>
<option value="2" selected="selected">two</option>
<option value="3">three</option>
</select>
又如:
$(document).ready
(
function()
{
$("#showLoadingDiv").click(function(){$("#dataLoad").show();}); //为指定按钮添加数据加载动态显示:即将DIV显示出来
$("#orderByFail").click(function(){$("#dataLoad").show();});
$("#orderByRate").click(function(){$("#dataLoad").show();});
$("#stats").change(function(){$("#dataLoad").show();}); //change
$("#indexPage").click(function(){$("#dataLoad").show();});
}
);
<select name="dictFilter.dictStatus" id="stats" onchange="javascript:location.href=this.value">
<option selected="selected" value="<%=basePath%>acauthinfo/authDefault.jsp?pageNum=1&StartTime=<%=pager.getStartTime()%>&field=<%=pager.getField()%>&sortOrder=<%=pager.getSortOrder()%>&EndTime=<%=pager.getEndTime()%>&pageSize=10" >每页10行</option>
<option selected="selected" value="<%=basePath%>acauthinfo/authDefault.jsp?pageNum=1&StartTime=<%=pager.getStartTime()%>&field=<%=pager.getField()%>&sortOrder=<%=pager.getSortOrder()%>&EndTime=<%=pager.getEndTime()%>&pageSize=20">每页20行</option>
<option selected="selected" value="<%=basePath%>acauthinfo/authDefault.jsp?pageNum=1&StartTime=<%=pager.getStartTime()%>&field=<%=pager.getField()%>&sortOrder=<%=pager.getSortOrder()%>&EndTime=<%=pager.getEndTime()%>&pageSize=30">每页30行</option>
<option selected="selected" value="">---请选择---</option>
</select>
HTML表单(Form)是HTML的一个重要部分,主要用于采集和提交用户输入的信息。
举个简单的例子,一个让用户输入姓名的HTML表单(Form)。示例代码如下:
<form action="http://www.blabla.cn/asdocs/html_tutorials/yourname.asp" method="get">
请输入你的姓名:
<input type="text" name="yourname">
<input type="submit" value="提交">
</form>
学习HTML表单(Form)最关键要掌握的有三个要点:
表单控件(Form Controls)
Action
Method
先说表单控件(Form Controls),通过HTML表单的各种控件,用户可以输入文字信息,或者从选项中选择,以及做提交的操作。比如上面的例句里,input type= "text"就是一个表单控件,表示一个单行输入框。
用户填入表单的信息总是需要程序来进行处理,表单里的action就指明了处理表单信息的文件。比如上面例句里的http://www.linkzj.cn/asdocs/html_tutorials/yourname.asp。
至于method,表示了发送表单信息的方式。method有两个值:get和post。get的方式是将表单控件的name/value信息经过编码之后,通过URL发送(你可以在地址栏里看到)。而post则将表单的内容通过http发送,你在地址栏看不到表单的提交信息。那什么时候用get,什么时候用post呢?一般是这样来判断的,如果只是为取得和显示数据,用get;一旦涉及数据的保存和更新,那么建议用post。
HTML表单(Form)常用控件(Controls)
HTML表单(Form)常用控件有:
input type="text" 单行文本输入框
input type="submit" 将表单(Form)里的信息提交给表单里action所指向的文件
input type="checkbox" 复选框
input type="radio" 单选框
select 下拉框
textArea 多行文本输入框
input type="password" 密码输入框(输入的文字用*表示)
表单控件(Form Control):单行文本输入框(input type="text")
单行文本输入框允许用户输入一些简短的单行信息,比如用户姓名。例句如下:
<input type="text" name="yourname">
表单控件(Form Control):
复选框(input type="checkbox")
复选框允许用户在一组选项里,选择多个。示例代码:
<input type="checkbox" name="fruit" value ="apple">苹果<br>
<input type="checkbox" name="fruit" value ="orange">桔子<br>
<input type="checkbox" name="fruit" value ="mango">芒果<br>
用checked表示缺省已选的选项。
<input type="checkbox" name="fruit" value ="orange" checked>桔子<br>
表单控件(Form Control):单选框(input type="radio")
使用单选框,让用户在一组选项里只能选择一个。示例代码:
<input type="radio" name="fruit" value = "Apple">苹果<br>
<input type="radio" name="fruit" value = "Orange">桔子<br>
<input type="radio" name="fruit" value = "Mango">芒果<br>
用checked表示缺省已选的选项。
<input type="radio" name="fruit" value = "Orange" checked>桔子<br>
表单控件(Form Control):下拉框(select)
下拉框(Select)既可以用做单选,也可以用做复选。单选例句如下:
<select name="fruit" >
<option value="apple">苹果
<option value="orange">桔子
<option value="mango">芒果
</select>
如果要变成复选,加muiltiple即可。用户用Ctrl来实现多选。例句:
<select name="fruit" multiple>
用户还可以用size属性来改变下拉框(Select)的大小。
表单控件(Form Control):多行输入框(textarea)
多行输入框(textarea)主要用于输入较长的文本信息。例句如下:
<textarea name="yoursuggest" cols ="50" rows = "3"></textarea>
其中cols表示textarea的宽度,rows表示textarea的高度。
表单控件(Form Control):密码输入框(input type="password")
密码输入框(input type="password")主要用于一些保密信息的输入,比如密码。因为用户输入的时候,显示的不是输入的内容,而是黑点符号。。例句如下:
<input type="password" name="yourpw">
表单控件(Form Control):提交(input type="submit")
通过提交(input type=submit)可以将表单(Form)里的信息提交给表单里action所指向的文件。例句如下:
<input type="submit" value="提交">
表单控件(Form Control):图片提交(input type="image")
input type=image 相当于 input type=submit,不同的是,input type=image 以一个图片作为表单的提交按钮,其中 src 属性表示图片的路径。
<input type="image" src ="http://www.blabla.cn/images/icons/go.gif" alt = "提交" NAME="imgsubmit">
1、<!--
通用提交按钮-->
<input type="submit" value="提交">
2、<!--
自定义提交按钮-->
<button type="Submit">提交</button>
3、<!--
图像按钮-->
<input type="image" src = "btn.png">
说明:用户提交按钮或图像按钮时,就会提交表单。使用<input>或<button>都可以定义提交按钮,只要将其特性的值设置为“submit”即可,而图像按钮则是通过<input>的type特性值设置为”image”来定义的。因此,只要我们单击一下代码生成的按钮,就可以提交表单。
4、
阻止表单提交
只要在表单中存在上面列出的任何一种按钮,那么相应表单控件拥有焦点的情况下,按回车键就可以提交表单。如果表单里没有提交按钮,按回车键不会提交表单。
以这种方式提交表单时,浏览器会在将请求发送给服务器之前触发submit事件。这样,我们就有机会验证表单数据,并据以决定是否允许表单提交。阻止这个事件的默认行为就可以取消表单提交。例如,下面代码会阻止表单提交:
var EventUtil = {
addHandler: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function (event) {
return event ? event : window.event;
},
preventDefault: function (event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
};
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function () {
//取得事件对象
event = EventUtil.getEvent(event);
//阻止默认事件
EventUtil.preventDefault(event);
});
调用preventDefault()方法阻止了表单提交。一般来说,在表单数据无效而不能发送给服务器时,可以使用这一技术。
5、在JavaScript中,以编程方式调用submit()方法也可以提交表单。
这种方式无需表单包含提交按钮,任何时候都可以正常提交表单。来看一个例子:
var form = document.getElementById("myForm");
//提交表单
form.submit();
在以调用submit()方法的形式提交表单时,不会触发submit事件,因此要记得在调用此方法之前先验证表单数字据。
提交表单时可能出现的最大问题,就是重复提交表单。在第一次提交表单后,如果长时间没有反映,用户可能会变得不耐烦。这时候,他们也许会反复单击提交按钮。结果往往很麻烦(因为服务器要处理重复请求),或者造成错误(如果是下了订单,那么可能会多定好几份)。
解决这一问题的办法有两个:
在第一次提交表单后就禁用提交按钮;
利用onsubmit事件处理程序取消后续的表单提交操作。