Java线程编程学习笔记(一)

"Java Thread Programming" by Paul Hyde

(本书在Amazon.com 5星推荐,不幸的是成书较早,内容都是针对JDK1.2的,不知道有没有关于新版本的)


2009.4.1


1.即使最简单的Java程序,比如打印“hello world”到Console,也运行在一个多线程的环境中(会有2个线程):main线程和垃圾收集线程。一个有GUI的Java程序更是多线程的,包含:事件分派线程和Painting GUI窗口的线程。


2.线程不是“免费的”。内存方面,每个Thread对象,除了本身需要的内存空间,还需要2个execution call stack,一个栈用来保存Java方法和变量的轨迹(track),另一个保存本地代码(如,c代码)的执行轨迹。CPU方面,需要执行叫做“context switching”的额外工作(就是挂起某个线程,保存该线程的场景,执行另一线程)。另外的开销就是“Thread”对象本身,考虑这样的情形:每5 minutes检查一次是否有新邮件;你不必每次都创建new thread,而应该让一个线程在“running”和“sleep”状态之间轮转。


3.Java的多线程是: Easy to Start,Tough to Master.  (深有体会)


4.线程的执行顺序问题:一定要记住,线程的循序可能会有多种!

比如:    

state1();

t.start();

state2();


其中,线程t的run方法是:

void run(){

  stateA();

}


执行顺序有可能是state1();state2();stateA(); 也有可能:state1();stateA();state2().


Caution:

A newly created thread may start executing (enter the run() method) at any time after start() is invoked. This means that the original thread might be swapped out before any statement that follows start() is executed.


5.线程从run()方法进入,在run()方法结束后死掉。死掉的线程无法restarted.


6.线程的启动使用t.start()方法。start()方法将会立即返回(return),并没有等到其他线程开始执行才返回。


7.native标明代码非Java code,而是JDK里的C/C++代码.

Many of the methods in Thread are listed with some of the following modifiers: native, final, static, and synchronized. As a quick review, native methods are implemented in non-Java code (typically C or C++ in the JDK).


8. 除了main thread外,Java VM 还会自动启动下面的thread(Java 1.2):

main

Finalizer

Reference Handler

Signal dispatcher

AWT-Windows

AWT-EventQueue-0

SunToolkit.PostEventQueue-0

Screen Updater


9.ThreadGroup/Thread 概念可类比文件系统的文件夹/文件概念

In Java, a ThreadGroup (much like a directory) can contain Threads and other ThreadGroups.


10.Thread.sleep()只能应用在当前线程,即Thread.currentThread上;在一个线程里对另一个调用sleep是不可能的。


11. volatile keyword:

the modifier volatile is included for some of the member variables. By indicating that a member variable is volatile, you inform the JavaVM that its value might be changed by one thread while being used by another. 


12.while(keepRunning){Thread.sleep(100);....} 使用这样的休眠时间,不会得到准确的秒针走动!因为这样除了休眠的100ms,还有其他代码运行的时间;加起来要比实际想要得到的时间慢。事实上,要让这样的时钟跟实际时钟同步,需要用变量sleeptime,即这样:Thread.sleep(sleepTime); sleepTime需要不断根据系统时钟来调整。


13. SecurityException是RuntimeException,因此不需要try/catch。所有的RuntimeException都不需要try/catch.


14. busy wait是对CPU资源的浪费,应当避免,替代以wait/notify方式。busy wait看起来像这样,即循环变量的更改依靠其他线程:

while (suspended) {

  Thread.sleep(200);

}


15. 守护线程(Daemon Threads)

守护线程用来做后台支持任务,只有当正常、非守护线程还在运行时候才需要。当VM检测到只剩下守护线程了,VM就会exit;否则如果还有非守护线程在运行,VM won't exit.

设置一个线程为守护线程,使用setDaemon(true)方法:

  Thread t = new XXXThread();

  t.setDaemon(true);


16.一个线程的优先级往往和制造它的线程优先级相同。main线程的优先级是5.大多数线程都是直接或间接有main产生的。因此大多数线程的优先级是5. 一般而言,线程的优先级在整个生命期间并不改变,但它确实可以改。


17.线程优先级对线程调度器而言,仅是一个“建议”,它并不能保证程序确实那样运行。不同的VM实现(implementation)对于线程调度问题差异很大。


18.Thread.yield()用来交出一个线程的运行权。线程调度器将终止当前线程的运行,去调度另外线程。yield不要乱用。


19.对一个方法加synchronized,表示:每次只允许一个线程进入这个方法。


20.定义public void synchronized doStuff(int val)会出错;正确应该是public synchronized void doStuff(int val)


21. 类的每个实例都有一个自身的对象级别锁。


22. 类级别的锁可以用来控制对static成员变量的并发访问,使用下面代码来事先类级别的锁:

synchronized ( ClassName.class ) {

  // body

}


23. 避免死锁是非常困难的,尝试遵循下面的原则:

1)尽量减少Hold lock的时间。对语句块使用synchronized;而不是对整个方法都使用

2)避免让代码一次占有2个或以上的lock。如果不能避免,就让占有第二个lock的时间尽量缩短

3)使用一个“大”的锁代替多个小的锁,使用这个锁来替代对象级别的lock


24. 为了避免"过早通知"(early notifications),应该将wait()置于while循环中,而不是if判断中;这样可以保证wait()之后总会有条件判断。


25. thread.join()

Thread的join()方法用来阻滞当前线程的运行,直到某特定线程死亡。例:threadX运行下面的代码,

try {

threadY.join();

} catch ( InterruptedException x ) {

}

threadX会阻塞,直到threadY死掉。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值