1 . wait() 方法使当前执行代码的线程进行等待,将当前线程置入"预执行队列",并且在wait()方法所在处停止执行,直到接到通知或者中断。 在调用wait之前,线程必须获得该对象的对象级别锁,即只能在同步方法或者同步代码块中才能调用wait方法。 调用wait()方法后当前线程自动释放锁。在从wait()返回之前,线程与其他线程竞争重新获得锁。
2 . notify() 用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机选出其中一个呈wait状态的线程对其发出notify, 并使它获取该对象的对象锁,值得注意的是在执行notify方法后当前线程不会马上释放该对象锁,呈wait状态的线程也不能马上获得该对象锁,要等到执行notify方法的线程将线程执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态的线程才可以获取该对象锁。当第一个获得了该对象锁的线程运行完毕之后它会释放掉该对象锁,此时如果对象没有再次使用notify方法,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,还会阻塞在wait状态,直到这个对象发出一个notify或者notifyAll. notify方法也要在同步方法或者同步代码块中才能调用,线程也必须获得该对象的对象级别锁
3 . 执行完同步代码块就会释放对象的锁;在执行同步代码块的过程中,遇到异常而导致线程终止锁也会被释放;在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程将会释放对象锁,而此线程对象将会进入线程等待池中等待被唤醒。
4.方法join()的作用是等待线程对象被销毁。也就是使所属线程对象x正常执行run()方法中的任务而使当前线程z无限期的阻塞,等待x销毁后再继续执行z后面的代码。
public class Test extends Thread{
@Override
public void run() {
int number = (int)(Math.random()*1000);
System.out.println(Thread.currentThread().getName()+" thread will sleep " + number + "ms");
try {
Thread.sleep(number);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
test.setName("test");
test.start();
test.join();
System.out.println("main thread execute after test thread end");
}
}
运行结果为:
test thread will sleep 595ms
main thread execute after test thread end
如果不调用join方法输出结果为:
main thread execute after test thread end
test thread will sleep 94ms
5 .方法join(long millis)和方法sleep(long millis)都有使线程等待一段时间的作用,但是join方法内部是使用wait方法实现的,所以join方法具有释放锁的特点,而sleep方法不会释放锁。
6 . 关键字synchronized和wait(),notify()/notifyAll()方法一起使用可以实现等待/通知机制,类ReentrantLock也可以实现同样的功能,但需要借助Condition对象来完成,Condition对象具有更好的灵活性,使用它可以实现多路通知功能,也就是一个Lock对象里面可以创建多个Condition(即对象监视器)对象实例,线程对象可以注册在指定的Condition中,从而有选择的进行通知,在线程调度上更灵活。而在使用notify()/notifyAll()方法进行通知的时候,被通知的线程却是由JVM随机选择的。
-
使用synchronized和wait,notify实现等待通知机制
public class WaitNotify1 {
public void waitMethod() {
System.out.println(" wait time begin at " + System.currentTimeMillis() / 1000);
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(" wait time end at " + System.currentTimeMillis() / 1000);
}
public void notifyMethod() {
System.out.println("notify time begin at " + System.currentTimeMillis() / 1000);
synchronized (this) {
this.notify();
}
System.out.println("notify time end at " + System.currentTimeMillis() / 1000);
}
public static void main(String[] args) throws InterruptedException {
WaitNotify1 wn1 = new WaitNotify1();
// 使用匿名内部类的方式启动两个线程分别调用wn1对象的waitMethod和notifyMethod
new Thread(new Runnable() {
@Override
public void run() {
wn1.waitMethod();
}
}).start();
Thread.sleep(1000);
new Thread(new Runnable() {
@Override
public void run() {
wn1.notifyMethod();
}
}).start();
/**
* 打印结果为:
* wait time begin at 1493194588
* notify time begin at 1493194589
* notify time end at 1493194589
* wait time end at 1493194589
*
*/
}
}
-
使用ReentrantLock和Condition对象实现等待-通知机制
public class WaitNotify2 {
private Lock lock = new ReentrantLock();
private Condition con = lock.newCondition();
public void waitMethod() {
try {
lock.lock();// 获得对象锁
System.out.println(" wait time begin at " + System.currentTimeMillis() / 1000);
con.await();// 线程进入等待
System.out.println(" wait time end at " + System.currentTimeMillis() / 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void notityMethod(){
try {
lock.lock();
System.out.println("notify time begin at " + System.currentTimeMillis() / 1000);
con.signal();// 唤醒线程
System.out.println("notify time end at " + System.currentTimeMillis() / 1000);
} finally{
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
WaitNotify2 wn2 = new WaitNotify2();
Thread4 thread = new Thread4(wn2);
thread.start();
Thread.sleep(1000);
wn2.notityMethod();
}
/**
* 打印结果为:
* wait time begin at 1493194430
* notify time begin at 1493194431
* notify time end at 1493194431
* wait time end at 1493194431
*
*/
}
class Thread4 extends Thread {
private WaitNotify2 wn2;
public Thread4(WaitNotify2 wn2) {
this.wn2 = wn2;
}
@Override
public void run() {
wn2.waitMethod();
}
}
7 . 生产者-消费者模式:
(1) 使用synchronized与wait,notify实现生产者-消费者模式
public class ProducersAndConsumers1 {
private List<String> list = new ArrayList<>();
public synchronized void produce() {
try {
while (list.size() == 1) {
System.out.println(Thread.currentThread().getName() + " begin waiting ");
this.wait();
System.out.println(Thread.currentThread().getName() + " end waiting ");
}
list.add("nulo");
this.notifyAll();
System.out.println("produced by " + Thread.currentThread().getName() + ",now size = " + list.size());
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized String consume() {
String value = "";
try {
while (list.size() == 0) {
System.out.println(Thread.currentThread().getName() + " begin waiting ");
this.wait();
System.out.println(Thread.currentThread().getName() + " end waiting ");
}
value = list.get(0);
list.remove(0);
this.notifyAll();
System.out.println(
"consumed by " + Thread.currentThread().getName() + ",now size = " + list.size());
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
public static void main(String[] args) throws InterruptedException {
ProducersAndConsumers1 pool = new ProducersAndConsumers1();
// 一生产一消费
new ProducerThread("producer",pool).start();
new ConsumerThread("consumer",pool).start();
/**
* 打印结果如下:
* consumer begin waiting
* producer end waiting
* produced by producer,now size = 1
* producer begin waiting
* consumer end waiting
* consumed by consumer,now size = 0
* consumer begin waiting
* producer end waiting
* produced by producer,now size = 1
* producer begin waiting
* consumer end waiting
* consumed by consumer,now size = 0
* consumer begin waiting
*
*/
// 一生产多消费
/*new ProducerThread("producer",pool).start();
new ConsumerThread("consumer1",pool).start();
new ConsumerThread("consumer2",pool).start();*/
// 多生产一消费
/*new ProducerThread("producer1",pool).start();
new ProducerThread("producer2",pool).start();
new ConsumerThread("consumer",pool).start();*/
// 多生产多消费
/*new ProducerThread("producer1",pool).start();
new ProducerThread("producer2",pool).start();
new ConsumerThread("consumer1",pool).start();
new ConsumerThread("consumer2",pool).start();*/
}
}
/**
*
* 生产者线程
*
* @Description
* @author niepei
* @date 2017年4月26日 下午4:44:17
* @version V1.3.1
*/
class ProducerThread extends Thread {
private ProducersAndConsumers1 pool;
public ProducerThread(String name,ProducersAndConsumers1 pool) {
super(name);
this.pool = pool;
}
@Override
public void run() {
while (true) {
pool.produce();
}
}
}
/**
*
* 消费者线程
*
* @Description
* @author niepei
* @date 2017年4月26日 下午4:44:29
* @version V1.3.1
*/
class ConsumerThread extends Thread {
private ProducersAndConsumers1 pool;
public ConsumerThread(String name,ProducersAndConsumers1 pool) {
super(name);
this.pool = pool;
}
@Override
public void run() {
while (true) {
pool.consume();
}
}
}
(2) 使用ReentrantLock和Condition对象实现生产者-消费者模式
public class ProducersAndConsumers2 {
private List<String> list = new ArrayList<>();
private Lock lock = new ReentrantLock();
private Condition con = lock.newCondition();
public void produce(){
try {
lock.lock();
while(list.size()==1){
System.out.println(Thread.currentThread().getName() + " begin waiting ");
con.await();
System.out.println(Thread.currentThread().getName() + " end waiting ");
}
list.add("nulo");
con.signalAll();
System.out.println("produced by " + Thread.currentThread().getName() + ",now size = " + list.size());
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public String consume(){
String value = "";
try {
lock.lock();
while(list.size()==0){
System.out.println(Thread.currentThread().getName() + " begin waiting ");
con.await();
System.out.println(Thread.currentThread().getName() + " end waiting ");
}
list.remove(0);
con.signalAll();
System.out.println("consumed by " + Thread.currentThread().getName() + ",now size = " + list.size());
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
return value;
}
public static void main(String[] args) throws InterruptedException {
ProducersAndConsumers1 pool = new ProducersAndConsumers1();
// 一生产一消费
new ProducerThread("producer",pool).start();
new ConsumerThread("consumer",pool).start();
/**
* 打印结果如下:
* consumer begin waiting
* producer end waiting
* produced by producer,now size = 1
* producer begin waiting
* consumer end waiting
* consumed by consumer,now size = 0
* consumer begin waiting
* producer end waiting
* produced by producer,now size = 1
* producer begin waiting
* consumer end waiting
* consumed by consumer,now size = 0
* consumer begin waiting
*/
}
}
/**
*
* 生产者线程
*
* @Description
* @author niepei
* @date 2017年4月26日 下午4:44:17
* @version V1.3.1
*/
class ProducerThread extends Thread {
private ProducersAndConsumers1 pool;
public ProducerThread(String name,ProducersAndConsumers1 pool) {
super(name);
this.pool = pool;
}
@Override
public void run() {
while (true) {
pool.produce();
}
}
}
/**
*
* 消费者线程
*
* @Description
* @author niepei
* @date 2017年4月26日 下午4:44:29
* @version V1.3.1
*/
class ConsumerThread extends Thread {
private ProducersAndConsumers1 pool;
public ConsumerThread(String name,ProducersAndConsumers1 pool) {
super(name);
this.pool = pool;
}
@Override
public void run() {
while (true) {
pool.consume();
}
}
}
8 . 类ThreadLocal可以使每个线程绑定自己的值,它解决的是变量在各个线程之间的隔离问题,也就是不同线程拥有自己的值,不同线程中的值是可以放入ThreadLocal中保存的
public class UseThreadLocal {
public static ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>();
private ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
function1();
/**
* 打印结果如下:
* THREAD_LOCAL in <main> is null
* THREAD_LOCAL in <test> is null
* THREAD_LOCAL in <test> is test
* THREAD_LOCAL in <main> is main
*/
new UseThreadLocal().function2();
/**
* 打印结果如下:
* threadLocal in <main> is null
* threadLocal in <test> is null
* threadLocal in <test> is test
* threadLocal in <main> is main
*/
}
public static void function1() throws InterruptedException {
System.out.println("THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get());
THREAD_LOCAL.set("main");
Thread a = new Thread("test") {
@Override
public void run() {
System.out.println(
"THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get());
THREAD_LOCAL.set("test");
System.out.println(
"THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get());
}
};
a.start();
a.join();
System.out.println("THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get());
}
public void function2() throws InterruptedException {
System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get());
threadLocal.set("main");
Thread a = new Thread("test") {
@Override
public void run() {
System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get());
threadLocal.set("test");
System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get());
}
};
a.start();
a.join();
System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get());
}
}
来源:https://www.cnblogs.com/pepper7/p/7196910.html