进程:系统分配资源的单位;
线程:处理器任务调度和执行的单位,线程之间共享进程资源。
线程通信:
解释:(A和B通电话,A需要打给B,B接听,A讲,B听;B讲,A听...)
我们在之前接触到的都是多个线程抢占CPU,谁抢到谁先执行,线程通信就是实现多个线程之间的通信,线程A执行,阻塞;线程B执行,阻塞,线程A执行,阻塞;线程B...
学习方法:
wait():线程阻塞,调用该方法的同时会释放同步监视器(锁) notify():唤醒被wait的线程,但是只唤醒一个线程(优先唤醒优先级高的线程) notifyAll():唤醒所有被wait的线程。 注意:wait()、notify()以及notifyAll()方法都是声明在Object类中的只能在同步代码块/同步方法中使用,必须保证和同步监视器的对象相同。
面试题:wait()和sleep()的区别?
- 声明位置不同:
- wait()声明在Object类中
- sleep()声明在Thread类中
- 作用范围不同:
- wait()只能声明在同步代码块/同步方法中
- sleep()声明位置比较随意
- 释放同步监视器:
- wait()在方法阻塞后会自动释放同步监视器
- sleep()在方法阻塞后不会自动释放同步监视器
自动释放锁的操作:
1.当前线程的同步方法、同步代码块执行结束;Lock锁,需要手动调用unlock()才能释锁;
2.当前线程在同步代码块、同步方法中遇到break、return终止了该代码块/ 该方法的继续执行;
3.当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束;
4.当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线 程暂停,并释放锁。
不会自动释放锁的操作:
1.线程执行同步代码块或同步方法时,程序调用Thread.sleep()、 Thread.yield()方法暂停当前线程的执行,并不会释放锁;
2.线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁(同步监视器);
3.应尽量避免使用suspend()和resume()来控制线程。
(suspend()和resume()是一对方法,挂起和开始。)
方法演示:
/*** 线程1和线程2交替输出100个数字*/publicclassDemo { publicstaticvoidmain(String[] args) { Numbernumber=newNumber(); Threadthread01=newThread(number); Threadthread02=newThread(number); thread01.setName("线程01"); thread02.setName("线程02"); thread01.start(); thread02.start(); } } classNumberimplementsRunnable{ privateintnum=1; Objectobj=newObject(); publicvoidrun() { while (true) { synchronized (obj) { //synchronized (this) {//如果此处的锁为this则下面执行的线程唤醒都应该为this.notify()/this.wait()或者省略this obj.notify(); if (num<=100) { System.out.println(Thread.currentThread().getName() +":"+num); num++; try { obj.wait(); } catch (InterruptedExceptione) { e.printStackTrace(); } }else { break; } } } }}