第一章:java线程
java程序的终止是指除守护线程意外的线程全部终止。守护线程是执行后台作业的线程,我们可以通过setDaemon方法把线程设置为守护线程
Thread类本身还实现了Runnable接口,并且持有run方法,但Thread类的run方法主体是空的,不执行任何操作,Thread类的run方法通常都由子类的run方法重写
java.util.concurrentt.ThreadFactory包中包含一个将线程创建抽象化的ThradFactory接口,利用该接口,我们可以将以Runnable作为传入参数并通过new创建Thread实例的处理隐藏在ThreadFactory内部
public class Printer implements Runnable {
private String message;
public Printer(String message){
this.message = message;
}
@Override
public void run() {
for (int i = 0;i < 100000;i++){
System.out.println(message);
}
}
}
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class type04 {
public static void main(String[] args) {
ThreadFactory factory = Executors.defaultThreadFactory();
factory.newThread(new Printer("Nice!")).start();
for (int i = 0;i < 100000;i++){
System.out.println("Goood");
}
}
}
线程的互斥机制称为监视。另外,获取锁有时也叫做“拥有监视”或“持有锁”
当前线程是否已获取某一对象的锁可以通过Thread.holdsLock方法来确认。当前线程获取对象obj的锁时,可使用assert来像下面这样表示出来
assert Thread.holdsLock(obj);
1.synchronized实例方法和synchronized代码块
synchronized void method(){
。。。。
}
等效于:
void method(){
synchronized(this){
}
}
2.synchronized静态方法和synchronized代码块
class Something{
static synchronized void method(){
}
}
等效于
class Something{
static void method(){
synchronized(Something.class){
}
}
}
wait(等待)方法会让线程进入等待队列。若要执行wait方法,线程必须持有锁,但是如果线程进入等待队列,便会释放其实例的锁。
等待队列是一个虚拟的概念。它既不是实例中的字段,也不是用户获取正在实例上等待的线程的列表的方法
notify(通知)方法会将等待队列中的一个线程取出。
notify唤醒的线程并不会在执行notify的一瞬间重新运行。因为在执行notify的那一瞬间,执行notify的线程还持有着锁,所以其他线程还无法获取这个实例的锁
刚被唤醒的线程去获取其他线程在进入wait状态时释放的锁。但现在锁是在谁的手中呢?对,就是执行notifyAll的线程正持有着锁。因此,唤醒的线程虽然都退出了等待队列,但都在等待获取锁,处于阻塞状态。只有在执行notifyAll的线程释放锁以后,其中一个幸运儿才能实际运行
如果线程未持有锁,那么会抛出IllegalMomitorStateException异常
总结:
- obj.wait()是将当前线程放入obj的等待队列中
- obj.notify()会从obj的等待队列中唤醒一个线程
- obj.notifyAll()会从obj的等待队列中唤醒所有线程
疑惑点:
wait,notify和notifyAll确实不是Thread类中固有的方法。但由于Object类是Java中所有类的父类,所以也可以说wait,notify,notifyAll都是Thread类的方法