Continued Chapter,Sleep()和Wait()的相同与区别?
相同:1从使用结果:都会让程序从从运行状态(Running)到阻塞状态(Blocked)。
区别:1Sleep()属于Thread类下的方法,
static void | sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 |
Continued Chapter
void | wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 |
void | wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 |
void | wait(long timeout, int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。 |
首先锁是什么?为什么要这个锁?锁(Lock):你可以把它想象成一个权限,只有当你拿到这个权限的时候你才能用。好了这个权限是什么呢?应为在线程当作,我们往往会编写大量的线程,这些线程不可能每个都重新开资源,把相同的资源拿出来,我们来同步代码块,这些代码块之类的就是锁了。
拿个别人的列子:
我要输出1到10000,建立10个线程来输出。
public class ThreadTest1 extends Thread {
private int threadNo;
public ThreadTest(int threadNo) {
this.threadNo = threadNo;
}
public static void main(String[] args) throws Exception {
for (int i = 1; i < 10; i++) {
new ThreadTest(i).start();
Thread.sleep(1);
}
}
@Override
public void run() {
for (int i = 1; i < 1000; i++) {
System.out.println("No." + threadNo + ":" + i);
}
}
}
这个只是简单的重写run()方法,再来看看带Synchonized()和Lock()
public class ThreadTest extends Thread {
private int threadNo;
public ThreadTest(int threadNo) {
this.threadNo = threadNo;
}
public static void main(String[] args) throws Exception {
for (int i = 1; i < 10; i++) {
new ThreadTest(i).start();
Thread.sleep(1);
}
}
@Override
public synchronized void run() {
for (int i = 1; i < 10000; i++) {
System.out.println("No." + threadNo + ":" + i);
}
}
}
这个使用了synchronized()同步方法的,Java中用同步监视器来解决进程并发造成的异常,我们上面用的是同步方法(讲下怎么使用呢就是用synchronized关键字来修饰方法,这样就称为同步方法)。虽然这样我们已经觉得很方便了,但是人的创造是无穷的,后来人们有在此基础上,提出了锁的概念,这个具有更强大的功能。
import java.util.concurrent.locks.ReentrantLock;
public class ThreadTest2 extends Thread {
private int threadNo;
private ReentrantLock lock=new ReentrantLock();
public ThreadTest2(int threadNo) {
this.threadNo = threadNo;
}
public static void main(String[] args) throws Exception {
for (int i = 1; i < 10; i++) {
new ThreadTest2(i).start();
Thread.sleep(1);
}
}
public void run() {
lock.lock();
try{
for (int i = 1; i < 1000; i++) {
System.out.println("No." + threadNo + ":" + i);
}
}
finally
{
lock.unlock();
}
}
}
这3个代码效果是一样的,但是我们发现这不是我们想要的。以为经过对比,我们发现无论有没有加synchronized()同步方法,还是直接上锁,我们都对的是run()方法,换个说法,线程自身作为对象锁,这显然没用。
如果我们要对线程进行同步,就要对同步对象进行上锁,这些对象需要共享且是唯一的,如何进行上锁呢?
public class ThreadTest extends Thread {
private int threadNo;
private String men;
public ThreadTest(int threadNo,String men) {
this.threadNo = threadNo;
this.men=men;
}
public static void main(String[] args) throws Exception {
String men=new String();
for (int i = 1; i < 10; i++) {
new ThreadTest(i,men).start();
Thread.sleep(1);
}
}
@Override
public void run() {
synchronized(men){
for (int i = 1; i < 1000; i++) {
System.out.println("No." + threadNo + ":" + i);
}
}
}
}
这个就可以实现每个线程单独打印出1到1000个数。
讲了这么多,那Sleep()和Wait()在对待锁到底有什么区别呢?
Sleep()执行的时候是不会释放锁的,该监控对象依然存在,只是时间到了才会释放。
而Wait()会放弃对象锁,进入等待此对象的等待池。除非被noifty()或者noiftyAll()唤醒。
Continued Chapter