- 浏览: 1147380 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (411)
- Java Foundation (41)
- AI/机器学习/数据挖掘/模式识别/自然语言处理/信息检索 (2)
- 云计算/NoSQL/数据分析 (11)
- Linux (13)
- Open Source (12)
- J2EE (52)
- Data Structures (4)
- other (10)
- Dev Error (41)
- Ajax/JS/JSP/HTML5 (47)
- Oracle (68)
- FLEX (19)
- Tools (19)
- 设计模式 (4)
- Database (12)
- SQL Server (9)
- 例子程序 (4)
- mysql (2)
- Web Services (4)
- 面试 (8)
- 嵌入式/移动开发 (18)
- 软件工程/UML (15)
- C/C++ (7)
- 架构Architecture/分布式Distributed (1)
最新评论
-
a535114641:
LZ你好, 用了这个方法后子页面里的JS方法就全不能用了呀
页面局部刷新的两种方式:form+iframe 和 ajax -
di1984HIT:
学习了,真不错,做个记号啊
Machine Learning -
赵师傅临死前:
我一台老机器,myeclipse9 + FB3.5 可以正常使 ...
myeclipse 10 安装 flash builder 4.6 -
Wu_Jiang:
触发时间在将来的某个时间 但是第一次触发的时间超出了失效时间, ...
Based on configured schedule, the given trigger will never fire. -
cylove007:
找了好久,顶你
Editable Select 可编辑select
锁永远是锁的对象!即使对加在static method方法上的所谓“锁住的是当前类”的锁,其实锁的也无非是Class的实例对象。
线程与 JVM 退出的关系:
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html
read it:
Chapter 20 of Inside the Java Virtual Machine - Thread Synchronization
http://www.artima.com/insidejvm/ed2/threadsynch.html
JLS Chapter 17. Threads and Locks
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.1
JDK1.5 concurrent 并发包专开:
http://wuaner.iteye.com/blog/1709915
The Java Tutorials -> Essential Java Classes -> Concurrency :
http://download.oracle.com/javase/tutorial/essential/concurrency/index.html
Synchronized Methods章节:
The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed)
Intrinsic Locks and Synchronization章节:
Every object has an intrinsic lock(The API specification often refers to this entity simply as a "monitor.",即一些文章中常说的“同步监视器”) associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to(必须) acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquistion of the same lock.
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
In this example, the addName method needs to synchronize changes to lastName and nameCount, but also needs to avoid synchronizing invocations of other objects' methods. (Invoking other objects' methods from synchronized code can create problems that are described in the section on Liveness.) (切记这一点:同步代码块中只应该包含需同步的当前对象的fields,而不要去同步其他对象的方法调用(如这里的list类型成员变量nameList的add()方法),否则容易产生死锁等问题)Without synchronized statements, there would have to be a separate, unsynchronized method for the sole purpose of invoking nameList.add.
Synchronized statements are also useful for improving concurrency(并发) with fine-grained(细粒度) synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.(专门用了两个作为成员变量的对象lock1和lock2,来实现分别对c1和c2的细粒度同步!经典啊!!!)
关于上链接中多次提及的 happens-before relationship:
http://dirkxu.iteye.com/blog/846922
http://www.iteye.com/problems/54095
Java Language Specification -> 14.18 The synchronized Statement::
http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#255769
Java Language Specification -> CHAPTER 17 Threads and Locks::
http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html#30206
The Java Virtual Machine Specification -> CHAPTER 8-Threads and Locks:
http://java.sun.com/docs/books/jvms/second_edition/html/Threads.doc.html
java中两种实现多线程的方式:
继承Thread类
实现Runnable接口
节选JDK Object notify()方法部分:
线程状态:
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.State.html
VisualVM 中看到的 threads,有 Running / Sleeping / Wait / Monitor 四种,其和 Thread.State 中定义的线程状态的关系是:
http://stringstream.blogspot.com/2011/11/thread-states-in-visualvm-profiler.html
synchronized两种实现:synchronized methods 和 synchronized statements
同步方法(被同步的方法不能是抽象类中的抽象方法和接口中的接口方法):
非静态方法
静态方法
同步块
Exploring Java: Chapter 6, Threads (里头一个关于生产者消费者问题的例子非常的好):
http://oreilly.com/catalog/expjava/excerpt/index.html
关于 Daemon Thread:
The Java Virtual Machine exits when the only threads running are all daemon threads.
http://journals.ecs.soton.ac.uk/java/tutorial/java/threads/daemon.html
http://www.jguru.com/faq/view.jsp?EID=43724
How can I create a daemon thread?
http://www.jguru.com/faq/view.jsp?EID=1251699
Thread范例:
http://www.java2s.com/Code/Java/Threads/CatalogThreads.htm
'Main' Thread in Java:
http://www.go4expert.com/forums/showthread.php?t=4178
java线程安全总结:
http://www.iteye.com/topic/806990
线程安全总结(二):
http://www.iteye.com/topic/808550
线程总结:
http://www.iteye.com/topic/768909
线程同步:
http://www.iteye.com/topic/164905
多线程,不得不说:
http://www.iteye.com/topic/158377
更好的把握线程<一>:Thread (线程)介绍:
http://www.iteye.com/topic/202329
java.util.concurrent:
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/package-summary.html
http://doc.java.sun.com/DocWeb/api/java.util.concurrent
Concurrent Programming with J2SE 5.0:
http://java.sun.com/developer/technicalArticles/J2SE/concurrency/
Java Concurrency / Multithreading:
http://www.vogella.de/articles/JavaConcurrency/article.html
实战Concurrent:
http://www.iteye.com/topic/363625
java并发编程-Executor框架:
http://www.iteye.com/topic/366591
Java多线程--让主线程等待所有子线程执行完毕:
http://www.iteye.com/topic/581476?page=2
淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和:
http://www.iteye.com/topic/711162
wait和sleep的区别:
Object的wait()方法的调用方是进入当前代码块的线程所锁定的对象!Thread的静态方法sleep()的调用方是进入当前代码块的线程!
wait释放锁,使得其他线程可以使用同步控制块或者方法;sleep方法不会释放锁;
wait方法属于Object;sleep方法属于Thread;
因为一个对象的wait(也包括notify/notifyAll)方法只能被拥有这个对象的monitor的线程所调用,所以wait方法需要和synchronized关键字配合使用,而sleep可以在任何地方使用;
关于他们的区别,网上还有一段话是这样说的:
“sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常”
这句话纯属扯淡。作为一个会抛出checked exception的方法,调用wait()方法岂可不对异常做处理!这句话想表述的道理其实是这样的:
调用sleep,原则上该用try-catch[-finally]语句块来捕获InterruptedException;而调用wait方法(以及notify和notifyAll),处理InterruptedException时可以捕获它,也可以继续throws它。
为什么外围不加synchronized的wait()方法调用会报“current thread not owner”?
原因很简单:单独的一条语句 wait(); = this.wait(); JDK有规定:对于Object的wait()、wait(long timeout)、wait(long timeout,int nanos)、notify()、notifyAll()这五个方法,should only be called by a thread that is the owner of this object's monitor。不加synchronized的话,则你无法保证执行到obj.wait()(或者notify()、notifyAll()等)这条语句的线程是拥有obj对象的线程锁(即monitor 同步监视器)的,wait调用无从谈起!
所以,synchronized锁了哪个对象,则拥有该对象锁的线程就可以调用该对象的wait()(以及notify()等)。如上面的这段代码:
则这里的wait()调用是这样的:
When you say myObject.wait() , what you're saying to the JVM is "mr. JVM, please stop executing the current Thread until myObject is unlocked".
But that's not what your (current) code block is saying: Since you're just calling wait() , you are, in fact, calling this.wait() . That is, you're calling wait on the this object.
You're saying to the JVM
"mr. JVM, please stop executing the current Thread until this is unlocked".
And the JVM is responding back to you by saying
"mr. Programmer, you don't own the this object, so how dare you tell me what to do with it?".
And the JVM is right: you don't own the this object. Why not? Because you didn't synchronize on this , you synchronized on lockedRecordMap .
You could have done so by synchronizing the method or syychronizing explicitly on this , but I don't think you want to in this case.
Thread join()方法:
http://download.oracle.com/javase/tutorial/essential/concurrency/join.html
synchronized methods 例子:
结合一个面试题深入剖析下synchronized statements 的锁机制:
该面试题见:
http://wuaner.iteye.com/admin/blogs/567792
这里仅对该面试题的正确答案做下分析,错误答案不再赘述。
附件中的Letters.rar即为下面的代码。
线程与 JVM 退出的关系:
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html
引用
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
1. The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place. (即调用System.exit())
2. All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
1. The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place. (即调用System.exit())
2. All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
read it:
Chapter 20 of Inside the Java Virtual Machine - Thread Synchronization
http://www.artima.com/insidejvm/ed2/threadsynch.html
JLS Chapter 17. Threads and Locks
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.1
JDK1.5 concurrent 并发包专开:
http://wuaner.iteye.com/blog/1709915
The Java Tutorials -> Essential Java Classes -> Concurrency :
http://download.oracle.com/javase/tutorial/essential/concurrency/index.html
引用
Synchronized Methods章节:
The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed)
Intrinsic Locks and Synchronization章节:
Every object has an intrinsic lock(The API specification often refers to this entity simply as a "monitor.",即一些文章中常说的“同步监视器”) associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to(必须) acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquistion of the same lock.
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
public void addName(String name) { synchronized(this) { lastName = name; nameCount++; } nameList.add(name); }
In this example, the addName method needs to synchronize changes to lastName and nameCount, but also needs to avoid synchronizing invocations of other objects' methods. (Invoking other objects' methods from synchronized code can create problems that are described in the section on Liveness.) (切记这一点:同步代码块中只应该包含需同步的当前对象的fields,而不要去同步其他对象的方法调用(如这里的list类型成员变量nameList的add()方法),否则容易产生死锁等问题)Without synchronized statements, there would have to be a separate, unsynchronized method for the sole purpose of invoking nameList.add.
Synchronized statements are also useful for improving concurrency(并发) with fine-grained(细粒度) synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.(专门用了两个作为成员变量的对象lock1和lock2,来实现分别对c1和c2的细粒度同步!经典啊!!!)
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } }
关于上链接中多次提及的 happens-before relationship:
http://dirkxu.iteye.com/blog/846922
引用
the result of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation.
http://www.iteye.com/problems/54095
引用
happens-before 是这样定义的,如果B能够看到A动作产生的结果,我们说A happens-before B
Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order. 同一个线程中,书写在前面的操作happen-before书写在后面的操作。
Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order. 同一个线程中,书写在前面的操作happen-before书写在后面的操作。
Java Language Specification -> 14.18 The synchronized Statement::
http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#255769
Java Language Specification -> CHAPTER 17 Threads and Locks::
http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html#30206
The Java Virtual Machine Specification -> CHAPTER 8-Threads and Locks:
http://java.sun.com/docs/books/jvms/second_edition/html/Threads.doc.html
java中两种实现多线程的方式:
继承Thread类
实现Runnable接口
节选JDK Object notify()方法部分:
引用
A thread becomes the owner of the object's monitor in one of three ways:
* By executing a synchronized instance method of that object.
* By executing the body of a synchronized statement that synchronizes on the object.(补充一下:这里的object如果是Class类型的,则和下面一条一样,得到的是类级锁;具体怎么得到Class的实例,参见http://wuaner.iteye.com/blog/1009134)
* For objects of type Class, by executing a synchronized static method of that class.
Only one thread at a time can own an object's monitor.
* By executing a synchronized instance method of that object.
* By executing the body of a synchronized statement that synchronizes on the object.(补充一下:这里的object如果是Class类型的,则和下面一条一样,得到的是类级锁;具体怎么得到Class的实例,参见http://wuaner.iteye.com/blog/1009134)
* For objects of type Class, by executing a synchronized static method of that class.
Only one thread at a time can own an object's monitor.
线程状态:
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.State.html
引用
public static enum Thread.State
extends Enum<Thread.State>
A thread state. A thread can be in one of the following states:
NEW
A thread that has not yet started is in this state.
RUNNABLE
A thread executing in the Java virtual machine is in this state.
BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED
A thread that has exited is in this state.
A thread can be in only one state at a given point in time. These states are virtual machine states which do not reflect any operating system thread states.
http://geekexplains.blogspot.com/2008/07/threadstate-in-java-blocked-vs-waiting.html
extends Enum<Thread.State>
A thread state. A thread can be in one of the following states:
NEW
A thread that has not yet started is in this state.
RUNNABLE
A thread executing in the Java virtual machine is in this state.
BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED
A thread that has exited is in this state.
A thread can be in only one state at a given point in time. These states are virtual machine states which do not reflect any operating system thread states.
VisualVM 中看到的 threads,有 Running / Sleeping / Wait / Monitor 四种,其和 Thread.State 中定义的线程状态的关系是:
http://stringstream.blogspot.com/2011/11/thread-states-in-visualvm-profiler.html
引用
Running - RUNNABLE
Sleeping - TIMED_WAITING
Wait - WAITING
Monitor - BLOCKED
Sleeping - TIMED_WAITING
Wait - WAITING
Monitor - BLOCKED
synchronized两种实现:synchronized methods 和 synchronized statements
同步方法(被同步的方法不能是抽象类中的抽象方法和接口中的接口方法):
非静态方法
引用
When a thread invokes a synchronized method(我的补充:非static), it automatically acquires the intrinsic lock for that method's object and releases it when the method returns
当一个线程调用一个synchronized(非static)方法时,自动获得这个方法的对象(即this对象)的monitor。
当一个线程调用一个synchronized(非static)方法时,自动获得这个方法的对象(即this对象)的monitor。
静态方法
引用
Since a static method is associated with a class, not an object. So when a static synchronized method is invoked, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
当一个线程调用一个static synchronized方法时,自动获得方法所在类对应的Class实例对象的monitor。
当一个线程调用一个static synchronized方法时,自动获得方法所在类对应的Class实例对象的monitor。
同步块
synchronized(obj) { obj.wait(); obj.notify(); ... }
Exploring Java: Chapter 6, Threads (里头一个关于生产者消费者问题的例子非常的好):
http://oreilly.com/catalog/expjava/excerpt/index.html
关于 Daemon Thread:
The Java Virtual Machine exits when the only threads running are all daemon threads.
http://journals.ecs.soton.ac.uk/java/tutorial/java/threads/daemon.html
引用
Any Java thread can be a daemon thread. Daemon threads are service providers for other threads running in the same process as the daemon thread. For example, the HotJava browser uses up to four daemon threads named "Image Fetcher" to fetch images from the file system or network for any thread that needs one. The run() method for a daemon thread is typically an infinite loop that waits for a service request.
When the only remaining threads in a process are daemon threads, the interpreter exits. This makes sense because when only daemon threads remain, there is no other thread for which a daemon thread can provide a service.
To specify that a thread is a daemon thread, call the setDaemon method with the argument true. To determine if a thread is a daemon thread, use the accessor method isDaemon.
When the only remaining threads in a process are daemon threads, the interpreter exits. This makes sense because when only daemon threads remain, there is no other thread for which a daemon thread can provide a service.
To specify that a thread is a daemon thread, call the setDaemon method with the argument true. To determine if a thread is a daemon thread, use the accessor method isDaemon.
http://www.jguru.com/faq/view.jsp?EID=43724
引用
The core difference between user threads and daemon threads is that the JVM will only shut down a program when all user threads have terminated. Daemon threads are terminated by the JVM when there are no longer any user threads running, including the main thread of execution. Use daemons as the minions they are.
[In short: daemon threads do not keep the program from quitting; user threads keep the program from quitting. -Alex]
In java we have two type of Threads : Daemon Thread and User Threads. Generally all threads created by programmer are user thread (unless you specify it to be daemon or your parent thread is a daemon thread). User thread are generally meant to run our programm code. JVM doesn't terminates unless all the user thread terminate.
On the other hand we have Daemon threads. Typically these threads are service provider threads. They should not be used to run your program code but some system code. These thread run paralley to your code but survive on the mercy of the JVM. When JVM finds no user threads it stops and all daemon thread terminate instantly. Thus one should never rely on daemon code to perform any program code.
For better understanding consider a well known example of Daemon thread : Java garbage collector. Garbage collector runs as a daemon thread to recalim any unused memory. When all user threads terminates, JVM may stop and garbage collector also terminates instantly.
[In short: daemon threads do not keep the program from quitting; user threads keep the program from quitting. -Alex]
In java we have two type of Threads : Daemon Thread and User Threads. Generally all threads created by programmer are user thread (unless you specify it to be daemon or your parent thread is a daemon thread). User thread are generally meant to run our programm code. JVM doesn't terminates unless all the user thread terminate.
On the other hand we have Daemon threads. Typically these threads are service provider threads. They should not be used to run your program code but some system code. These thread run paralley to your code but survive on the mercy of the JVM. When JVM finds no user threads it stops and all daemon thread terminate instantly. Thus one should never rely on daemon code to perform any program code.
For better understanding consider a well known example of Daemon thread : Java garbage collector. Garbage collector runs as a daemon thread to recalim any unused memory. When all user threads terminates, JVM may stop and garbage collector also terminates instantly.
How can I create a daemon thread?
http://www.jguru.com/faq/view.jsp?EID=1251699
引用
The following is a simple program which creates a thread within the context of the main thread of execution. Since the main thread is a user thread the created thread will also be a user thread unless it's status is set otherwise. A couple of notes about the following code. If the created threads status is not set or false is passed to the setDameon() method then the created thread will fully execute. This is because the main thread cannot return until all non-daemon threads are finished. Setting the status to true in our case doesn't give our daemon thread much time to do it's bussiness since the main method will quickly execute then return thus stopping our daemon thread dead in it's tracks. We would be lucky to get a print out of one year!. So what can we do? Either we can put the main thread to sleep for an amount of time (enough to give our dameon thread time to do it's business) or simply make it a non-daemon thread by setting it's status to false.
这里例子很好的说明了daemon thread(附件里有):当线程t不是守护线程时,其输出结果是完整的1001行输出;当其是守护线程时,具体会输出多少行就无法预知了。
public class DaemonThreadTest { public static void main(String[] args) { Thread t = new Thread(new DaemonThread(525.00f, 0.09f)); t.setDaemon(true); t.start(); // try { // Thread.sleep(250); // must give the deamon thread a chance to run! // } catch (InterruptedException ei) { // 250 mills might not be enough! // System.err.println(ei); // } } } class DaemonThread implements Runnable { private float principal; private float futureval; private float rate; private float i; public DaemonThread(float principal, float rate) { this.principal = principal; this.rate = rate; } public void run() { for (int year = 0; year <= 1000; year++) { i = (1 + rate); futureval = principal * (float) Math.pow(i, year); System.out.print(principal + " compounded after " + year + " years @ " + rate + "% = " + futureval); System.out.println(); } } }
这里例子很好的说明了daemon thread(附件里有):当线程t不是守护线程时,其输出结果是完整的1001行输出;当其是守护线程时,具体会输出多少行就无法预知了。
Thread范例:
http://www.java2s.com/Code/Java/Threads/CatalogThreads.htm
'Main' Thread in Java:
http://www.go4expert.com/forums/showthread.php?t=4178
java线程安全总结:
http://www.iteye.com/topic/806990
线程安全总结(二):
http://www.iteye.com/topic/808550
线程总结:
http://www.iteye.com/topic/768909
线程同步:
http://www.iteye.com/topic/164905
多线程,不得不说:
http://www.iteye.com/topic/158377
更好的把握线程<一>:Thread (线程)介绍:
http://www.iteye.com/topic/202329
java.util.concurrent:
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/package-summary.html
http://doc.java.sun.com/DocWeb/api/java.util.concurrent
Concurrent Programming with J2SE 5.0:
http://java.sun.com/developer/technicalArticles/J2SE/concurrency/
Java Concurrency / Multithreading:
http://www.vogella.de/articles/JavaConcurrency/article.html
实战Concurrent:
http://www.iteye.com/topic/363625
java并发编程-Executor框架:
http://www.iteye.com/topic/366591
Java多线程--让主线程等待所有子线程执行完毕:
http://www.iteye.com/topic/581476?page=2
淘宝面试题:如何充分利用多核CPU,计算很大的List中所有整数的和:
http://www.iteye.com/topic/711162
wait和sleep的区别:
Object的wait()方法的调用方是进入当前代码块的线程所锁定的对象!Thread的静态方法sleep()的调用方是进入当前代码块的线程!
wait释放锁,使得其他线程可以使用同步控制块或者方法;sleep方法不会释放锁;
wait方法属于Object;sleep方法属于Thread;
因为一个对象的wait(也包括notify/notifyAll)方法只能被拥有这个对象的monitor的线程所调用,所以wait方法需要和synchronized关键字配合使用,而sleep可以在任何地方使用;
关于他们的区别,网上还有一段话是这样说的:
“sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常”
这句话纯属扯淡。作为一个会抛出checked exception的方法,调用wait()方法岂可不对异常做处理!这句话想表述的道理其实是这样的:
调用sleep,原则上该用try-catch[-finally]语句块来捕获InterruptedException;而调用wait方法(以及notify和notifyAll),处理InterruptedException时可以捕获它,也可以继续throws它。
为什么外围不加synchronized的wait()方法调用会报“current thread not owner”?
原因很简单:单独的一条语句 wait(); = this.wait(); JDK有规定:对于Object的wait()、wait(long timeout)、wait(long timeout,int nanos)、notify()、notifyAll()这五个方法,should only be called by a thread that is the owner of this object's monitor。不加synchronized的话,则你无法保证执行到obj.wait()(或者notify()、notifyAll()等)这条语句的线程是拥有obj对象的线程锁(即monitor 同步监视器)的,wait调用无从谈起!
所以,synchronized锁了哪个对象,则拥有该对象锁的线程就可以调用该对象的wait()(以及notify()等)。如上面的这段代码:
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } }
则这里的wait()调用是这样的:
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { lock1.wait(); // this.wait(); //这里不可调this.wait();因为进入这段同步代码块的线程并没有拥有当前MsLunch实例对象的monitor!!! c1++; } } public void inc2() { synchronized(lock2) { lock2.wait(); // this.wait(); //这里不可调this.wait();因为进入这段同步代码块的线程并没有拥有当前MsLunch实例对象的monitor!!! c2++; } } }http://www.coderanch.com/t/232016/threads/java/Current-thread-not-owner
引用
synchronized (lockedRecordMap) { ... wait(); //Error!because:you don't own the this object, so how dare you tell me what to do with it??!! ... }
When you say myObject.wait() , what you're saying to the JVM is "mr. JVM, please stop executing the current Thread until myObject is unlocked".
But that's not what your (current) code block is saying: Since you're just calling wait() , you are, in fact, calling this.wait() . That is, you're calling wait on the this object.
You're saying to the JVM
"mr. JVM, please stop executing the current Thread until this is unlocked".
And the JVM is responding back to you by saying
"mr. Programmer, you don't own the this object, so how dare you tell me what to do with it?".
And the JVM is right: you don't own the this object. Why not? Because you didn't synchronize on this , you synchronized on lockedRecordMap .
You could have done so by synchronizing the method or syychronizing explicitly on this , but I don't think you want to in this case.
Thread join()方法:
http://download.oracle.com/javase/tutorial/essential/concurrency/join.html
引用
The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,
t.join();
causes the current thread to pause execution until t's thread terminates.
调用join()方法的线程t会pause当前线程!直到t线程terminated!
例子:t.join();
causes the current thread to pause execution until t's thread terminates.
调用join()方法的线程t会pause当前线程!直到t线程terminated!
public class TestJoin { static void threadMessage(String message) { String threadName = Thread.currentThread().getName(); System.out.format("%s: %s%n", threadName, message); } public static void main(String[] args) { Thread thread = new Thread(new SimpleThread()); thread.start(); try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } for(int i=0; i<9; i++) { threadMessage("i am running ..."); } } private static class SimpleThread implements Runnable { public void run() { for(int i=0; i<9; i++) { threadMessage("i am running ..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }输出:
引用
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
Thread-0: i am running ...(注:每一秒输出一次)
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
main: i am running ...
synchronized methods 例子:
/** *synchronized static 方法是为类加的锁;synchronized非static 方法是为对象加的锁。 * 说明: * 当某一线程访问一个对象的synchronized非static方法时,其他线程不可以访问该对象的其他synchronized非static方法,可以访问其他的方法(包括普通的非synchronized方法,和static synchronized方法) * 当某一线程访问一个对象的static synchronized方法时,其他线程不可以访问该对象的其他static synchronized方法,可以访问其他的方法(包括普通的非synchronized方法,和synchronized非static方法) */ public class TestSync { public static void main(String[] args) { /** * 择一 */ Thread1 t = new Thread1(); //Thread2 t = new Thread2(); //Thread3 t = new Thread3(); //Thread4 t = new Thread4(); //Thread5 t = new Thread5(); Thread thread = new Thread(t); thread.setName("sub"); thread.start(); try { Thread.sleep(500); //这句话是为了确保在main 线程执行t的方法前,sub线程已进入t的同步代码块 } catch (InterruptedException e) { e.printStackTrace(); } t.m2(); } } /** * * 输出: Thread main 进入方法 m2(), i=1000 (大概五秒钟后...) Thread sub 进入方法 m1(), i=1000 */ class Thread1 implements Runnable { private int i = 10; public void run() { m1(); } synchronized public void m1(){ i = 1000; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m1(), i=" + i); } public void m2() { System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m2(), i=" + i); } } /** * * 输出: (大概五秒钟后...) Thread sub 进入方法 m1(), i=1000 Thread main 进入方法 m2(), i=1000 */ class Thread2 implements Runnable { private int i = 10; public void run() { m1(); } synchronized public void m1(){ i = 1000; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m1(), i=" + i); } public synchronized void m2() { System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m2(), i=" + i); } } /** * 输出: Thread main 进入方法 m2(), i=1000 (大概五秒钟后...) Thread sub 进入方法 m1(), i=1000 */ class Thread3 implements Runnable { private static int i = 10; public void run() { m1(); } public synchronized static void m1() { i = 1000; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m1(), i=" + i); } public synchronized void m2() { System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m2(), i=" + i); } } /** * 输出: (大概五秒钟后...) Thread sub 进入方法 m1(), i=1000 Thread main 进入方法 m2(), i=1000 */ class Thread4 implements Runnable { private static int i = 10; public void run() { m1(); } public synchronized static void m1() { i = 1000; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m1(), i=" + i); } public static synchronized void m2() { System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m2(), i=" + i); } } /** * 输出: Thread main 进入方法 m2(), i=1000 (大概五秒钟后...) Thread sub 进入方法 m1(), i=1000 */ class Thread5 implements Runnable { private static int i = 10; public void run() { m1(); } public synchronized void m1() { i = 1000; try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m1(), i=" + i); } public synchronized static void m2() { System.out.println("Thread " + Thread.currentThread().getName() + " 进入方法 m2(), i=" + i); } }
结合一个面试题深入剖析下synchronized statements 的锁机制:
该面试题见:
http://wuaner.iteye.com/admin/blogs/567792
这里仅对该面试题的正确答案做下分析,错误答案不再赘述。
附件中的Letters.rar即为下面的代码。
public class Letters extends Thread { private String name; public Letters(String name) { this.name = name; } public void write() { System.out.print(Thread.currentThread().getName() + name); System.out.print(Thread.currentThread().getName() + name); } public static void main(String[] args) { Letters l1 = new Letters("X"); Letters l2 = new Letters("Y"); l1.start(); l2.start(); try { Thread.sleep(500); //这句话是为了确保在main方法执行l2的write方法前,两个sub线程已进入Letters的同步代码块 } catch (InterruptedException e) { e.printStackTrace(); } l2.write(); // synchronized(System.out) { //不加这行会报“current thread not owner” // System.out.println("main 线程得到了 System.out 的锁"); // System.out.notify(); //替换成notifyAll()效果会不一样。 // } } public void run() { synchronized(Letters.class) { try { Thread.sleep(5000); ///System.out.wait(); } catch (InterruptedException e) { e.printStackTrace(); } write(); } } //OK /** * * 如果锁的是Letters.class,输出可能为: * 1 mainYmainY(大概五秒钟后..)Thread-0XThread-0X(大概五秒钟后..)Thread-1YThread-1Y * 2 mainYmainY(大概五秒钟后..)Thread-1YThread-1Y(大概五秒钟后..)Thread-0XThread-0X * 这里想说明的是: * main线程对非同步方法write()的调用并没有因为Thread-0(or Thread-1)持有了Letters的类锁而受影响,说明了: * 当一个线程持有一个类的类锁(即这个类对应的Class实例的锁)的时候,其他线程可以访问该类的非同步方法(也可以访问该类的synchronized非static方法,但不可以访问该类的static synchronized方法) * * * 如果锁的是System.out,输出可能为: * 1 (大概五秒钟后..)Thread-1YThread-1Y(大概五秒钟后..)Thread-0XThread-0XmainYmainY * 2 (大概五秒钟后..)Thread-0XThread-0X(大概五秒钟后..)Thread-1YThread-1YmainYmainY * 这里想说明的是: * System.out这个对象是静态的,只有一份,所以这里可以通过对这个对象加锁实现题目要求; * 但为什么main线程对Letters的非同步方法write()的调用会受到Thread-0(or Thread-1)的影响那(被阻塞)?原因在于write方法中调用了System.out.print!详细解释如下: * first,看JDK中的几条东西: * *System类中:public final static PrintStream out = nullPrintStream(); //注意该out变量是static的,所以只会有一份 * *PrintStream类中: * public void print(String s) { * if (s == null) { * s = "null"; * } * write(s); * } * private void write(String s) { * try { * synchronized (this) { * ensureOpen(); * textOut.write(s); * textOut.flushBuffer(); * charOut.flushBuffer(); * if (autoFlush && (s.indexOf('\n') >= 0)) * out.flush(); * } * } * catch (InterruptedIOException x) { * Thread.currentThread().interrupt(); * } * catch (IOException x) { * trouble = true; * } * } * PrintStream类的write()方法中的synchronized (this)正是造成main线程被阻塞的原因所在!详析如下: * main线程没有任何阻碍的到达了Letters的非同步方法write()的内部;当在该方法内部调用 * System.out.print(),继而调用PrintStream.write()时,main线程试图锁住this(这里的this,即是那独有一份的System静态成员变量System.out) * 结果很不幸,System.out已经被两个子线程中的其中一个提前锁定了!所以,main线程被阻塞。 * * * 扩展开来: * 只要在不同线程进来时,能保证这里要锁定的对象是同一个对象,就可以满足题目的要求! * 举几个例子,锁定以下对象都是可以保证结果符合题目要求的: * synchronized(new Letters("").getClass()) , 这个和锁 Letters.class 是完全一样的,都是得到Letters这个类的类级锁。 * synchronized(Class.forName("Letters")) 这个和锁 Letters.class 也是一样的。 * synchronized("abc") "abc" 仅指向常量池中独有的那一份,故这样做可以。 * synchronized(int.class) int.class在jvm中也是唯一的。 * synchronized(System.out.getClass()) * * * 这个题目在Letters的run()方法中调用Letters的非同步方法write(),给人一种假象,似乎对象加锁后对象所属类的非同步方法也无法访问了。 * 其实根本就不是这么回事!千万别被这种假象迷惑。 * 因为synchronized关键字是写在run方法内、write方法外,所以只有走run方法的线程(哪些线程会走run方法?当然是基于该线程实现类所start的线程对象们;当然,直接调用该run()方法的线程也会走),在访问write()方法时是无并发串行的来. * 而其他线程对Letters的非同步方法write()的调用不会受任何影响,正如上面“在锁Letters.class的时候main对write()的调用不受影响”的例子所展示的那样。 * * * 如果去掉代码中的两行Thread.sleep(): * 对于锁Letters.class的情况:main线程调用非同步方法write()产生的两个输出在最终输出串中的位置根本就是无法预知的;唯有两个子线程他们之间的输出是有序的(具体他俩谁在前那就不一定了).如: * Thread-0XmainYThread-0XmainYThread-1YThread-1Y * mainYThread-0XmainYThread-0XThread-1YThread-1Y * mainYThread-1YmainYThread-1YThread-0XThread-0X * Thread-0XmainYThread-0XThread-1YThread-1YmainY * Thread-0XmainYmainYThread-0XThread-1YThread-1Y * 对于锁System.out的情况:main线程调用非同步方法write()产生的两个输出在最终输出串中的位置仍然是无法预知的;两个子线程的输出也有上面的特点,但有一点与上面的不同:对于任一子线程,其产生的两个输出一定是紧挨着的!如: * Thread-0XThread-0XmainYThread-1YThread-1YmainY * mainYThread-0XThread-0XmainYThread-1YThread-1Y * Thread-0XThread-0XmainYThread-1YThread-1YmainY * mainYThread-1YThread-1YmainYThread-0XThread-0X * Thread-1YThread-1YThread-0XThread-0XmainYmainY * * * 这个例子说明的问题: * 如果一个线程的实现类的run()方法,内部有对同一对象实例(这里的同一对象,指的是不管进来的是哪个线程,这个对象永远不变)的synchronized()块(在run()方法本身的外围加上synchronized不行;因为这种方式锁定的是this对象,不会在所有线程进来时都是同一个),则基于该线程类所start的各个不同线程实例,就只能是串行的了!没有并发的可能性。 * * * 代码中注释掉的是对wait()和notify()做测试的例子;还有待补充。 */ }
- TestSync.rar (934 Bytes)
- 下载次数: 5
- Letters.rar (2.7 KB)
- 下载次数: 5
- DaemonThreadTest.rar (578 Bytes)
- 下载次数: 2
发表评论
-
J2SE Evolution
2013-04-11 15:39 1185Java 7 New Features Java SE 7 ... -
未完 Java: IO & NIO(new I/O)
2013-01-11 20:56 2051适用: event and data-driven apps ... -
未完 java设计: naming convention | 命名规范
2012-11-20 16:45 2129应该遵循的规范: 类/接口/属性名,使用名词或形容词 ... -
未完 Java: enum 枚举
2012-11-19 20:29 1815http://stackoverflow.com/que ... -
Java多线程之 concurrent 并发包
2012-11-01 07:47 2021Java Tutorials -> Concur ... -
未完 Java Tips & Tricks & Notes
2012-09-12 10:00 1128Hidden Features of Java: h ... -
未完 Java Socket
2012-09-12 08:42 1013Java SocketJava SocketJava Sock ... -
Java For-each Loop & Iterable | 增强型For循环和Iterable接口
2012-09-11 21:50 2059增强型For循环没什么好说的,Just see link ... -
未完 Java Collections | 容器
2012-09-06 11:35 1830Sources: http://docs.oracle.com ... -
Java object Initialization (class Instantiation) | 对象的初始化(即类的实例化)
2012-09-03 09:12 3002类实例即对象 ... -
未完Java class&interfac 's Loading, Linking and Initializing | 类与接口的加载、链接和初始化
2012-08-31 19:01 1670JVM装载一个类的时候,首先检查他有没有父类,如果有父类则装载 ... -
未完 java Static 总结
2012-08-31 18:47 1402static可以用来修饰: 字段 Fields 方法 Meth ... -
未完 JVM Runtime Data Areas & Java Memory Model | 内存分配模型 & Java数据存储
2012-08-31 18:43 1890Java虚拟机内存分配模型 需精读:Chapter 5 of ... -
Java Data Types & Literals | 数据类型 和 字面量
2012-08-30 18:12 3940Java数据类型划分: OR http:// ... -
未完 Variables 变量 (Instance/Class/Local)
2012-08-29 10:59 1700Local/Instance/Class Variables ... -
未完 Regular Expressions | 正则表达式
2011-08-25 11:43 1528Extended Regular Expression ... -
java Date(util.Date/sql.Date/sql.Timestamp/sql.Time) & Oracle DATE Type 时分秒 精度问题
2011-05-17 09:32 3959遇到的问题描述: 数据库为Oracle,其jdbc驱动为ojd ... -
Java byte code (bytecode)
2011-05-04 02:55 3884keys: bytecode, byte code, opco ... -
Java Classloading Mechanism : ClassLoader & ASM & 动态字节码增强
2011-04-21 13:29 2424Setting the class path: http:// ... -
class literal & instance.getClass() & Class.forName(String className)
2011-04-20 12:33 2336常用的几种取得Class类实例的方式: 1 class lit ...
相关推荐
在Java中,线程并发可以通过多种方式实现,包括继承Thread类、实现Runnable接口以及使用ExecutorService和Future等高级API。下面将详细探讨这些知识点。 首先,Java中创建线程主要有两种方法。一种是通过继承Thread...
Java的synchronized关键字用于实现线程同步,它可以修饰方法或代码块,确保同一时间只有一个线程可以执行特定代码。volatile关键字则用于确保变量的可见性和有序性,防止指令重排序对多线程环境造成的影响。更高级的...
总的来说,Java多线程同步借助`java.util.concurrent`包提供的工具,使得开发者可以更高效、安全地编写并发程序。掌握这些工具的使用不仅能够优化代码性能,还能减少潜在的并发问题,提升软件的可靠性和可维护性。...
4. **ReentrantLock可重入锁**:除了`synchronized`,Java还提供了一个更高级的锁机制——`java.util.concurrent.locks.ReentrantLock`。它具有与`synchronized`相似的功能,但提供了更多的灵活性,如尝试获取锁、...
此外,Java还提供了并发工具类,如`java.util.concurrent`包下的`ExecutorService`、`Semaphore`、`CountDownLatch`等,这些工具可以帮助开发者更高效地管理和协调线程,提高并发性能。 总之,Java的多线程和并发...
3. **java.util.concurrent 包**:这个包提供了许多高级的线程同步工具,如Semaphore(信号量)、CyclicBarrier(回环屏障)、CountDownLatch(倒计时器)等。这些工具可以更灵活地控制线程的并发执行。 4. **...
另外,java.util.concurrent包提供了高级的并发工具,如Semaphore(信号量)、CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁),它们为复杂的线程同步和协调提供了强大支持。 在处理并发问题时,死锁是一...
文章指出,Java多线程执行过程的机制是基于Java虚拟机(JVM)的内存模型的,Java内存模型的规范是统一的, Java多线程并发问题最终都会反映在Java的内存模型上。因此,文章强调了控制多个线程对某个资源的有序访问或...
Java平台提供了丰富的API支持并发编程,如`java.util.concurrent`包下的各种类和接口,这些工具可以帮助开发者更高效地管理多线程环境下的任务调度和数据共享问题。 ### Java并发编程基础 #### 1. 多线程基础 - **...
Java线程同步是多线程编程中的一个重要概念,它用于解决在并发环境下多个线程对共享资源的访问问题,以防止数据的不一致性。在Java中,线程同步的机制主要包括锁、同步块、同步方法、volatile关键字以及线程通信(如...
线程间的通信和同步是并发编程中的关键问题,Java提供了synchronized关键字、wait()、notify()和notifyAll()等机制来解决这些问题。 4. **并发工具类** 除了线程和阻塞队列外,Java并发库还包括其他有用的工具类,...
Java多线程并发实战与源码分析是Java开发中至关重要的一部分,它涉及到程序性能优化、系统资源高效利用以及复杂逻辑的正确同步。本书主要聚焦于Java多线程的基础理论和实际应用,虽然书中实例和源码相对较少,但仍然...
此外,Java并发编程还包括对并发容器的使用,如ArrayList、LinkedList、HashSet、HashMap等基础容器在并发环境下可能存在问题,Java提供了一些线程安全的容器,如Vector、HashTable以及java.util.concurrent包下的...
2. **同步机制**:Java提供了`synchronized`关键字来实现线程间的同步,确保共享资源在同一时刻只被一个线程访问,防止数据不一致。 3. **volatile关键字**:volatile可以确保变量在多线程环境下的可见性和有序性,...
除了锁,Java还提供了其他同步机制,如`java.util.concurrent`包下的并发工具类。其中包括`Semaphore`(信号量)用于限制同时访问特定资源的线程数量,`CountDownLatch`(倒计时器)用于一次性阻塞多个线程,直到...