在水木上看到的问题
int[] intArray = new int[]{1, 2, 3, 4};
List>Integer< list = new ArrayList>Integer<();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
List listFromArray = Arrays.asList(intArray);
System.out.println(listFromArray);
System.out.println(list);
输出结果是
[[I@c17164]
[1, 2, 3, 4]
也就是说Arrays.asList()并没有返回一个{1,2,3,4}的List
原因在于,JDK5中asList接受变长参数表了,把intArray作为单独的参数传递给asList方法的时候,编译器会把它当作一个Object处理,于是返回了只有一个元素的List,而这个元素应该就是指向int[]的引用。
解决方法之一是把intArray声明为Integer[],即
Integer[] intArray = new Integer[]{new Integer(1), new Integer(2), new Integer(3), new Integer(4)};
List>Integer< listFromArray2 = Arrays.asList(intArray2);
System.out.println(listFromArray2);
这样就能看到预期结果了

posted @ 2007-04-22 20:26 ZelluX 阅读(840) | 评论 (0)编辑 收藏

posted @ 2007-04-22 20:26 ZelluX 阅读(790) | 评论 (0)编辑 收藏

2007-03-24 22:17:50

继续保持记笔记的习惯。

CSS Mastery: Advanced Web Standards Solutions

1. 应该只在没有现有元素能够实现区域分割的情况下使用div元素。如
>div id="mainNav"<
>ul<
>li<1>/li<
...
>/ul<
>/div<
就应当使用
>ul id="mainNav"<
...
>/ul<
代替

2. 伪类(Pseudo-classes)
如a:link a:visited 称为链接伪类,只能用于锚(anchor)元素。
input:focus tr:hover a:active 称为动态伪类,理论上可以应用于任何元素。

3. 通用选择器(the universal selector)
* {
margin: 0px;
}
作用于所有元素。

4. 高级选择器
Firefox Safari 均支持,IE 6及更低版本不支持,因此在重要元素上要避免使用。
1)子选择器
如#nav < li仅作用于nav的第一层li,li中包含的列表项不受影响
2)属性选择器
abbr[title] {border-bottom: 1px dotted #999;}
abbr[title]:hover {cursor: help;}
修改了abbr的title属性,不过第一行貌似在IE7中也没有效果,Firefox下可以。

posted @ 2007-04-22 20:25 ZelluX 阅读(398) | 评论 (0)编辑 收藏

2007-03-14 10:32:46
先看完coreservlets, core java把Java学好,恩

posted @ 2007-04-22 20:25 ZelluX 阅读(181) | 评论 (0)编辑 收藏

2007-03-13 16:08:26
灌个水,Java Bean真是好东西,加上Eclipse的自动写代码就更爽了,恩

posted @ 2007-04-22 20:25 ZelluX 阅读(333) | 评论 (0)编辑 收藏

2007-03-02 16:24:28
新浪的博客编辑器貌似漂亮了不少,还增加了首行自动缩进
1. 公平性
创建ReentrantLock对象时,使用true参数可以激活公平锁策略(fair locking policy):
Lock fareLock = new ReentrantLock(true);
公平锁有助于等待时间最长的线程的恢复运行,当然这种机制也影响了程序性能。公平锁比普通锁慢很多,因此默认关闭。
2. 锁测试、超时
线程调用lock方法的时候很有可能停滞,可以使用tryLock()方法代替。获得锁成功,tryLock返回true,反之返回false,且线程可以继续运行。
可以在tryLock中增加时限参数,如
if (myLock.tryLock(1000, TimeUnit.MILLISECONDS) ...
表示时限为1000毫秒,TimeUnit是一个枚举类,它的值有SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS。
带时限参数的tryLock方法和lock方法一样遵循公平原则,但是无参的tryLock却不会,不过可以用tryLock(0, TimeOut.SECONES)代替。
lock方法无法被打断,如果一个线程在等待锁的时候被中断,它会继续处于停滞状态,知道获得锁为止。而使用带时限的tryLock方法,如果线程在等待时被中断,它会抛出InterruptedException异常。这很有用,可以防止程序锁死的发生。
类似的还有lockInterruptibly,和tryLock很相似,只是时限无限长。
Condition也可以设置时限:
myCondition.await(100, TimeUnit.MILLISECONDS);
这样await方法有三种结束的可能:其他线程调用的signal或signalAll方法激活该线程;时限到;线程被中断(抛出InterruptedException)。
对于第三种可能,如果不想被中断(一般很少这样),调用awaitUninterruptibly方法。
3. 读写锁
ReentrantReadWriteLock类用于许多线程从一个数据源读写的情况。readLock()和writeLock()返回内置的读写锁。
4. 为什么stop和suspend方法要被废弃
两个方法有一个共同点:都试图未经其他线程允许就控制它们的行为。
首先来看stop方法,这个方法结束了所有执行中的方法,包括run方法,当一个线程被停止的时候,它立即放弃了所有它锁住的对象,这会使那些对象处于非正常状态。如转帐的transferThread在取出资金后存入资金前被停止,就会产生事故。因为一个线程试图结束另一个线程的时候,它并不知道此时该行为是否安全。
然后是suspend方法,suspend方法并不会损害对象。但是当你调用suspend方法挂起一个线程时,这个线程拥有的锁也就同时被挂起了,此时如果调用suspend方法的线程试图获得那把锁,那么整个程序就会锁死:被挂起的线程需要恢复,能够恢复它的线程因为锁而停滞。
这种情况在GUI中尤为常见,例如银行用户界面有暂停和继续两个按钮,暂停按钮能够挂起所有运行中的线程,另外paintComponent方法能够画出每个帐号的图表。
假设某个线程获得了bank对象的锁,此时用户按下了暂停按钮,所有的转帐线程挂起,其中一个拥有bank的锁。由于某个原因,帐号图表需要重绘,调用了paintComponent方法,后者调用了getBalances方法,又因为无法获得bank对象的锁,程序锁死。而此时用户自然也无法按下继续按钮。
如果想安全地使用挂起功能,可以自己设计一个suspendRequested变量。
public void run()
{
while (. . .)
{
. . .
if (suspendRequested)
{
suspendLock.lock();
try { while (suspendRequested) suspendCondition.await(); }
finally { suspendLock.unlock(); }
}
}
}
public void requestSuspend() { suspendRequested = true; }
public void requestResume()
{
suspendRequested = false;
suspendLock.lock();
try { suspendCondition.signalAll(); }
finally { suspendLock.unlock(); }
}
private volatile boolean suspendRequested = false;
private Lock suspendLock = new ReentrantLock();
private Condition suspendCondition = suspendLock.newCondition();

posted @ 2007-04-22 20:25 ZelluX 阅读(269) | 评论 (0)编辑 收藏

以空格代替Tab, 养成良好编码风格

  在编写程序代码时用空格代替Tab,可以避免由于编辑器对tab显示方式不同引起的代码错乱,是一种良好的编程风格。

  1. JBuilder
  在Project pane中右键点击项目名称,在弹出的菜单中选择"Properties..."以打开项目属性对话框。再选择 "Formatting" 属性选项,把其中的 "Use tab char" 前面的钩选取消即可。同时还可以在此指定语句块和折行的缩进空格数目。

  2. Eclipse
  在菜单栏选择 "Window" - "Preference" 打开自定义对话框。

  (1) 对于java代码,在 "java - code style -formatter" 中设置。在 "Select a profile" 中选择 "Java Conversions", 然后点击 "Show..." 按钮,把 "Indentation" 属性的 "Tab Policy" 改成 "Space Only", 同时设置缩进空格数;另外在 "Line Wrapping" 中设置折行的缩进为 1 个indent单位。 点击 "Apply" 或 "OK" ,将提示你为当前的属性配置方案另取一个名字。

  (2) 如果使用了MyEclipse, 对于JSP/ HTML/ JavaScript/ XML/ CSS/ SQL/ DTD代码,要分别在各自的 "Source" 属性中选中 "indent using spaces", 并设置缩进空格数。

  (3) 以上设置对整个workspace生效,但你还可以单独设置特定项目的java代码风格。

  3. UltraEdit
  在“高级”-“配置...”-“编辑”中设置“制表符使用空格代替”。
  另外,在“格式”菜单中还可以选择对空格和制表符进行相互转换。

posted @ 2007-04-22 20:25 ZelluX 阅读(1938) | 评论 (2)编辑 收藏

2007-03-01 16:26:54
omg,打了半天忘了存盘了,运行Java程序时一个crash死机了。。。
直接把今天看的部分放上来了
1. The synchronized Keyword
Before the Lock and Condition interfaces were added to JDK 5.0, the Java language used a different concurrency mechanism. Ever since version 1.0, every object in Java has an implicit lock. If a method is declared with the synchronized keyword, then the object's lock protects the entire method. That is, to call the method, a thread must acquire the object lock.
In other words,

public synchronized void method()
{
method body
}

is the equivalent of

public void method()
{
implicitLock.lock();
try
{
method body
}
finally { implicitLock.unlock(); }
}

For example, instead of using an explicit lock, we can simply declare the transfer method of the Bank class as synchronized.
The implicit object lock has a single associated condition. The wait method adds a thread to the wait set, and the notifyAll/notify methods unblock waiting threads. In other words, calling wait or notifyAll is the equivalent of

implicitCondition.await();
implicitCondition.signalAll();

However, the implicit locks and conditions have some limitations. Among them are:
You cannot interrupt a thread that is trying to acquire a lock.
You cannot specify a timeout when trying to acquire a lock.
Having a single condition per lock can be inefficient.
The virtual machine locking primitives do not map well to the most efficient locking mechanisms available in hardware.
What should you use in your codeLock and Condition objects or synchronized methods? Here is our recommendation:
1)It is best to use neither Lock/Condition nor the synchronized keyword. In many situations, you can use one of the mechanisms of the java.util.concurrent package that do all the locking for you. For example, on page 48, you will see how to use a blocking queue to synchronize threads that work on a common task.
2)If the synchronized keyword works for your situation, by all means, use it. You write less code and have less room for error. Example 1-5 shows the bank example, implemented with synchronized methods.
3)Use Lock/Condition if you specifically need the additional power that these constructs give you.
Note: At least for now, using the synchronized keyword has an added benefit. Tools that monitor the virtual machine can report on the implicit locks and conditions, which is helpful for debugging deadlock problems. It will take some time for these tools to be extended to the java.util.concurrent mechanisms.
2. Monitors
The locks and conditions are powerful tools for thread synchronization, but they are not very object oriented. For many years, researchers have looked for ways to make multithreading safe without forcing programmers to think about explicit locks. One of the most successful solutions is the monitor concept that was pioneered by Per Brinch Hansen and Tony Hoare in the 1970s. In the terminology of Java, a monitor has these properties:
~ A monitor is a class with only private fields.
~ Each object of that class has an associated lock.
~ All methods are locked by that lock. In other words, if a client calls obj.method(), then the lock for obj is automatically acquired at the beginning of the method call and relinquished when the method returns. Because all fields are private, this arrangement ensures that no thread can access the fields while another thread manipulates them.
~ The lock can have any number of associated conditions.
However, a Java object differs from a monitor in three ways:
~ Fields are not required to be private.
~ Methods are not required to be synchronized.
~ The lock has only one condition.
This disrespect for security enraged Per Brinch Hansen. In a scathing review of the multithreading primitives in Java, he wrote: "It is astounding to me that Java's insecure parallelism is taken seriously by the programming community, a quarter of a century after the invention of monitors and Concurrent Pascal. It has no merit." [Java's Insecure Parallelism, ACM SIGPLAN Notices 34:3845, April 1999]
3. Synchronized Blocks
Recall that each object has a lock. A thread can acquire the lock in one of two ways, by calling a synchronized method or by entering a synchronized block. If the thread calls obj.method(), it acquires the lock for obj. Similarly, if a thread enters a block of the form

synchronized (obj) // this is the syntax for a synchronized block
{
critical section
}
then the thread acquires the lock for obj. The lock is reentrant. If a thread has acquired the lock, it can acquire it again, incrementing the hold count. In particular, a synchronized method can call other synchronized methods with the same implicit parameter without having to wait for the lock.
It is legal to declare static methods as synchronized. If such a method is called, it acquires the lock of the associated class object. For example, if the Bank class has a static synchronized method, then the lock of the Bank.class object is locked when it is called.
4. Volatile 域
现在的处理器和编译器很有可能产生一些同步时的错误:
~ 多处理器的计算机会临时地在寄存器或缓存中存放数据,因此在不同处理器上运行的线程可能会从同一个内存区域获得不同的值。
~ 编译器为了提高效率,会重新排列指令顺序。但它们在操作时假设只有当有明确的更改指令时,内存数据才会改变。然而,实际上该数据有可能被另一线程修改。
如果你用锁保护由多线程访问的代码,就不会遇到这些问题。编译器在清洗缓冲区时会考虑到锁的存在,也不会错误地修改指令顺序。具体细节参见http://www.jcp.org/en/jsr/detail?id=133http://www-106.ibm.com/developerworks/java/library/j-jtp02244.html
Brian Goetz指出了应该何时使用同步:当你更改了某个下次可能会被其他线程访问的变量,或者访问了一个上一次可能被其他线程修改的变量,你就必须使用synchronization。
volatile关键字提供了一种同步实例域的访问的机制。如果把某一字段声明为volatile,编译器和虚拟机就会考虑到该数据域可能会同时被另一线程访问。
例如,boolean值的字段done可能被一个线程修改,并由另一个线程访问。有两种方法实现:
1)
public synchronized boolean isDone() {return done;}
private boolean done;
这种方法有一个潜在的缺陷:如果另一个方法锁住了对象,isDone方法可能会停滞。
2)
public boolean isDone() {return done;}
private volatile boolean done;
当然,访问一个volatile字段会比访问普通字段慢一些。
总结一下,对某字段的并发访问在以下情况中是安全的:
~ volatile字段
~ final字段,并且在构造器完成后就被修改。
~ 访问操作被锁保护
5. 锁死 Deadlocks
死锁的几种情况:(以银行转帐为例)
1)帐号1: $2,000 帐号2: $3,000
先试图从帐号1转3000到帐号2,再试图从帐号2转4000到帐号1。
容易得出,最后两个线程都会锁死。
2)有许多帐号,其中
帐号1: $1,990 其余帐号都是 $990
线程1: 从帐号1转$995到帐号2
其余线程: 从自己的帐号转出$995到其他帐号
显然,除了线程1,其余线程都被停滞。
线程1操作后,帐号1剩$995,帐号2剩$1,985,此时线程1使用signal方法随机恢复了一个线程,假设是线程3,但恢复后发现帐号3的资金仍不够转帐,于是继续停滞。
假设此时线程1又执行了从帐号1转出$997的指令,于是线程1也停滞。
系统锁死。
罪魁祸首就是signal方法。

posted @ 2007-04-22 20:25 ZelluX 阅读(346) | 评论 (0)编辑 收藏

2007-02-28 16:34:52
*
Condition只是一个接口,怎么可以直接调用它的方法呢?于是查源码(发现这个东西才是最彻底的),从ReentrantLock开始,
ReentrantLock.newCondition()
-
-
-
看到了详细的方法实现 ^_^
1. 两三个线程同时修改某个对象,如果仅由访问先后来决定结果的话,会出现各种结果。这种情况被称为race condition。
2. 防止这种情况的发生,必须知道如何同步访问(synchronize the access)。
3. javap -c -v ClassName 可以反编译一个.class文件。
4. 锁住对象
早期版本的Java使用synchronized关键词,JDK5以后引入了ReentrantLock类。
使用ReentrantLock类保护代码块的基本轮廓:
myLock.lock(); // a ReentrantLock object
try
{
critical section
}
finally
{
myLock.unlock(); // make sure the lock is unlocked even if an exception is thrown
}
这样第一个线程调用lock方法锁住myLock后,第二个线程调用lock方法就会被block,并且得等到第一个线程调用myLock.unlock()后才能继续。
ReentrantLock类允许被多次锁定,它记录了呼叫的嵌套形式。大致是这个意思,原文是

The lock is called reentrant because a thread can repeatedly acquire a lock that it already owns. The lock keeps a hold count that keeps track of the nested calls to the lock method. The thread has to call unlock for every call to lock in order to relinquish the lock. Because of this feature, code that is protected by a lock can call another method that uses the same locks.

For example, the TRansfer method calls the getTotalBalance method, which also locks the bankLock object, which now has a hold count of 2. When the getTotalBalance method exits, the hold count is back to 1. When the transfer method exits, the hold count is 0, and the thread relinquishes the lock.

In general, you will want to protect blocks of code that require multiple operations to update or inspect a data structure. You are then assured that these operations run to completion before another thread can use the same object.

5. Condition Objects
Conditon Objects用来管理得了访问权,却实际并不能做有用功的线程。
以银行帐户转帐为例,转帐时要确定转出源的资金数不少于要转出的金额。
首先不能这样简单的写代码:
if (bank.getBalance(from) <= amount)
bank.transfer(from, to, amount);
这种代码完全有可能在if语句判断完成后,transfer之前停滞,这样在调用transfer的时候,可能帐户当前的资金已经不是if语句判断那个时候的数目了。
也就是说,测试可行性和实际操作必须一起进行,之间不能有中断。
可以用一个lock把测试和操作绑定起来:
public void transfer(int from, int to, int amount)
{
bankLock.lock();
try
{
while (accounts[from] > amount)
{
// wait
. . .
}
// transfer funds
. . .
}
finally
{
bankLock.unlock();
}
}
这样还是有问题,帐户资金不够移出时,会困在while块中等待资金拨入这个帐户,但由于bankLock已经被锁定,所以其他线程不能进行拨入操作,进入了死循环。这就是condition object产生的原因。
一个lock对象可以有一个或多个相关的condition object,可以通过newCondition方法获得一个条件对象,通常用实际条件命名每个条件对象,如
class Bank
{
public Bank()
{
. . .
sufficientFunds = bankLock.newCondition();
}
. . .
private Condition sufficientFunds;
}
当transfer方法发现当前资金不够时,调用
sufficientFunds.await();
这样当前线程就会停滞,并解除lock。
await方法调用后,线程进入对应Condition的等待区,直到另一个线程调用同一Condition的signalAll方法才会解除block状态,并等待再次被线程管理器激活。
如果一个线程调用了condition.await方法,却没有其他线程调用condition.signalAll,这个线程就进入了deadlock情况。如果所有其他的线程都进入了等待区,而最后一个线程也调用了condition.await,那么整个程序就挂起了。
因此最好的调用signalAll的时机是在每次对象的状态被改变,而这个改变有可能使得等待区的线程有进展的时候。如Bank中每次成功转帐之后。
另一个方法,signal,仅仅从等待区中随机选择一个进程并释放。
注意:线程只能在获得了lock权以后才能调用condition的await, signal, 和signalAll。

posted @ 2007-04-22 20:25 ZelluX 阅读(325) | 评论 (0)编辑 收藏

2007-02-28 14:05:52
1. 线程优先权
每个线程都有一定的优先权,且默认从父线程继承优先权,也就是运行这个线程的线程。可以使用setPriority方法设置,从MIN_PRIORITY(1)到MAX_PRIORITY(10),NORM_PRIORITY是5。
然而线程优先权更多的是由系统决定的。如在WinXP/NT有若干个优先等级,某些Java的优先级也自动对应到相应的等级上。但是在Sun JVM for Linux中,线程优先权被忽视,所有的线程享有相同的优先权。
所以,最好把线程仅仅看成是对线程管理器的hint。不要由线程优先级来决定你的程序结构。
注意:在使用优先级的时候,如果某几个很少会停滞的线程享有高优先级,很有可能低优先级的线程就不会被运行。
2. Daemon进程
把一个进程变为daemon进程可以调用方法setDaemon(true)。所谓daemon,就是只用来服务其他进程的进程,所以当只有daemon进程运行时,JVM就退出了。
3. 进程组
ThreadGroup g = new ThreadGroup(String groupName);
注意groupName必须唯一。
加入线程:
Thread t = new Thread(g, String threadName);
进程组中可以有子进程组,新创建的子进程组默认属于当前进程组。
ThreadGroup类的方法:
int activeCount() 返回组中活动的线程数。
int enumerate(Thread[] list) 获得组中每个活动进程的引用,返回实际加入list的进程数。
ThreadGroup getParent()
void interrupt 中止所有的进程和子进程组。
4. 处理未捕获异常
线程的run方法并不能抛出任何checked异常,但因为一个unchecked异常而结束。
在线程结束前,异常会被传递给一个处理器。
异常处理器必须实现了Thread.UncaughtExceptionHandler接口,后者只有一个方法
void uncaughtException(Thread t, Throwable e)
可以在任何线程中使用setUncaughtExceptionHandler方法设置处理器,也可以使用Thread的静态方法setDefaultUncaughtExceptionHandler为每个线程指定默认的处理器。如果不为每个独立的线程指定处理器,处理器默认为该线程的线程组对象。
ThreadGroup类实现了Thread.UncaughtExceptionHandler接口,它的uncaughtException方法按下列步骤进行:
1)如果该进程组有父进程组,调用父进程组的uncaughtException方法。
2)否则,如果Thread.getDefaultUncaughtExceptionHandler返回一个非null的引用,该处理器被调用。
3)如果仍未找到,且Throwable参数是ThreadDeath的实例,不进行任何处理。
4)上述都未执行的话,进程名和Throwable参数的调用栈就会输出到System.err上

posted @ 2007-04-22 20:25 ZelluX 阅读(275) | 评论 (0)编辑 收藏

仅列出标题
共39页: First 上一页 28 29 30 31 32 33 34 35 36 下一页 Last 
posts - 403, comments - 310, trackbacks - 0, articles - 7
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理