在执行同步代码期间,线程可以调用对象的wait()方法,释放对象锁,然后进入等待状态,并且可以调用notify()方法或notifyAll()方法来通知其他线程正在等待. notify()方法仅唤醒一个线程(等待队列中的第一个线程),并允许他获取锁. notifyAll()方法唤醒所有等待此对象的线程,并允许它们获取锁(并非所有唤醒线程都被允许)获取锁,但让它们竞争).
JDK5新添加了Lock接口及其实现类之一,RecentrantLock(可重入锁). 锁也可以用来实现多线程同步. 具体来说,它提供了以下方法来实现多线程同步:
1,锁定(). 以阻塞的方式获取锁,即如果获取了锁,则立即返回;如果另一个线程持有该锁,则当前线程在知道已获取该锁之后等待并返回.
2,tryLock(). 以非阻塞方式获取锁. 只需尝试获取锁,如果获得了锁,则立即返回true,否则立即返回false.
3,tryLock(长时间超时,TimeUnit uint). 如果获得了锁,它将立即返回true,否则它将等待参数给定的时间单位. 在等待过程中,如果获得了锁,则返回true,如果等待超时,则返回false.
4. LockInterruptible(). 如果获得了锁,请立即返回;如果未获取该锁,则当前线程将处于休眠状态,直到获取该锁,或者当前线程被另一个线程中断(将接收到InterruptedException). 它与lock()方法之间的最大区别是,如果lock()方法无法获取该锁,则它将始终处于阻塞状态,而interr()方法将被忽略. 示例如下:

import java.util.comcrurrent.locks.Lock;
import java.util.comcrurent.locks.ReentrantLock;
public class Test{
public static void main(String[] args) throws Interrupted Exception{
final Lock lock = new ReentrantLock();
lock.lock();
Thread t1 = new Thread (new Runnable(){
public void run(){
try{
lock.lockInterruptibly();
//lock.lock();编译器报错
}catch(InterruptedException e){
System.out.println("interrupted.");
}
}
});
t1.start();
t1.interrupt();
Thread.sleep(1);
}
}
该程序的结果如下:
中断.
sleep()是一种将线程的执行暂停一段时间的方法. wait()也是一种挂起线程执行的方法. 例如,当线程交互时,如果线程向同步对象x发出一个wait()调用请求,则该线程将暂停执行,并且被调用对象进入等待状态,直到被唤醒或等待时间到期.
具体地说,sleep()方法和wait()方法之间的区别主要体现在以下几个方面:
1. 原理不同. sleep()方法是Thread类的静态方法,线程使用它来控制自己的进程. 它将暂停该线程的执行一段时间,并为其他线程提供执行机会. 当计时时间到期时,该线程将自动“唤醒”,例如,当该线程执行计时功能时,每秒打印一次时间,那么您需要在打印之前添加一个sleep()方法允许自己每隔1秒执行一次的方法,该过程就像一个闹钟一样. wait()方法是Object类的一种方法,用于线程之间的通信. 该方法将导致当前持有对象锁定的进程等待“唤醒”之前其他线程调用notify()方法(或notifyAll方法),但是开发人员还可以给他一点时间来自动“唤醒”. 支持wait()方法的方法包括notify( )方法和notifyAll()方法.
2. 处理锁的机制不同. 因为sleep()的主要功能是在一段时间内挂起线程的执行,所以当时间到时,它将自动恢复,并且不涉及线程之间的通信. wait()方法是不同的. 当调用wait()方法时,线程将释放其持有的锁,以便其他线程可以使用该线程所在的对象中的其他同步数据. 举一个简单的例子,如果A拿到,他可以每10分钟使用sleep()方法调谐一次频道,在这10分钟内,仍在他手中.
3. 使用范围不同. 由于wait()方法的特殊含义call 多次调用 崩溃 线程安全,必须在同步控制方法或同步语句块中使用它,而sleep()方法可以在任何地方使用.
在Java语言中,可以使用stop()方法和suspend()方法来终止线程的执行. 使用Thread.stop()终止线程时,它将释放所有已锁定的监视资源. 如果当前由这些监视资源保护的任何对象处于不一致状态,则其他线程将“看到”该不一致状态,这可能导致程序执行中的不确定性,并且很难将问题确定为. 调用suspend()方法容易产生死锁**(死锁是指两个或多个进程在执行过程中由于资源竞争而互相等待的现象. 如果没有外力,它们都将无法提前)**. 由于调用suspend()方法不会释放该锁,因此会引起问题: 如果使用suspend来挂起锁定的线程,则在恢复锁之前不会释放它. 如果调用suspend()方法,线程将尝试获取相同的锁,程序将死锁. 鉴于上述两种方法的不安全性,Java语言不建议使用以上两种方法终止线程.
通常推荐的方法是让线程本身结束进入Dead状态. 线程进入Dead状态,即在执行run()方法之后,即,如果要停止执行线程,则必须提供某种方式使线程自动结束run()方法,意味着如果要停止线程的执行,我们必须为线程提供一种自动结束run()方法执行的方法. 在实现中,可以通过设置标志来控制是否执行循环,并使用此方法让线程离开run()方法来终止进程. 下面显示了如何结束线程:
public class MyThread implements Runnable{
private volatile Boolean flag;
public void stop(){
flag = false;
}
public void run(){
while(flag);
//do something
}
}
在上面的示例中,尽管可以使用MyThread的stop()方法来终止县,但是还存在一些问题: 当线程未运行时(当调用sleep()方法时或在wait()时)方法被调用或被I / O阻止时),上述方法不可用. 这时,您可以使用interrupt()方法来打破阻塞情况. 调用interrupt()方法时,将引发InterruptedException异常. 您可以通过在run()方法中捕获此异常来使线程安全退出. 具体实现如下:
public class MyThread{
public static void main (String[] args){
Thread thread = new Thread(new Runnable){
public void run(){
System.out.println("thread go to sleep");
try{
//用休眠来模拟线程被阻塞
Thread.sleep(5000);
System.out.println("thread finish");
}catch(InterruptedException e){
System.out.println("thread is interuptes!");
}
}
});
thread.start():
thread.interrupt();
}
}
程序的运行结果为:
线程进入睡眠状态
线程中断了!
如果程序由于I / O而停顿并进入非运行状态,则基本上它必须等待I / O完成才能退出该状态. 在这种情况下,您不能使用interrupt()方法使程序离开run()方法. 让程序离开run()方法是使用close()方法关闭流. 在这种情况下,将抛出IOException. run()方法可以通过捕获此异常来安全地结束线程.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-182864-2.html
为了祖国的统一大业
不要听他的
难拢人心