java多线程学习笔记(八)
本节开始线程间通信:
- 使用wait/notify实现线程间通信
- 生产者/消费者模式的实现
- 方法join的使用
- ThreadLocal类的使用
可以通过使用 sleep() 结合 while(true) 死循环来实现线程间的通信
通过使用while(true){ if(条件) } 来检查某个数据,满足条件时结束循环,线程会处在不断运行的状态,会浪费CPU资源
wait/notify 机制应运而生(等待通知机制)
方法wait()的作用是使当前执行代码的线程等待,将当前线程放置到“预执行队列”中,并且在wait所在的代码行处停止执行,知道接收到通知或者被中断为止。在调用wait之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait方法。执行wait方法之后,当前线程会释放锁。
方法notify也要在同步方法或者同步块中使用,即在调用前必须获得对象级别的锁。notif会随机挑选一个wait状态的线程,对其发送notify通知,并使他等待获得该对象的对象锁。在执行notify方法之后,当前线程不会立马释放掉该对象锁,呈wait状态的线程也不能马上获得该对象锁,要等待执行notify方法的线程将所有程序执行完也就是退出synchronized代码块后,当前线程才会释放锁。
public class Mythread1 extends Thread { private Object lock; public Mythread1 (Object lock){ super(); this.lock = lock; } @Override public void run(){ try{ synchronized (lock){ System.out.println("开始 wait time "+System.currentTimeMillis()); lock.wait(); System.out.println("结束 wait time "+System.currentTimeMillis()); } }catch (InterruptedException e){ e.printStackTrace(); } } } public class MyThread2 extends Thread { private Object lock; public MyThread2(Object lock) { super(); this.lock = lock; } @Override public void run() { synchronized (lock) { System.out.println("开始 notify time " + System.currentTimeMillis()); lock.notify(); System.out.println("结束 notify time " + System.currentTimeMillis()); } } } public class Test { public static void main(String[] args) { try{ Object lock = new Object(); Mythread1 t1 = new Mythread1(lock); t1.start(); Thread.sleep(3000); MyThread2 t2 = new MyThread2(lock); t2.start(); }catch (InterruptedException e){ e.printStackTrace(); } } }
开始 wait time 1575421393700 开始 notify time 1575421396701 结束 notify time 1575421396702 结束 wait time 1575421396703
public class ThreadA extends Thread{ private MyList list; public ThreadA(MyList list){ super(); this.list = list; } @Override public void run(){ try{ synchronized(list){ for(int i =0; i<10; i++){ list.add(); if(list.size() == 5){ System.out.println("已发出通知。"); list.notify(); } System.out.println("add item "+(i+1)+"..."); Thread.sleep(1000); } } }catch(InterruptedException e){ e.printStackTrace(); } } } public class ThreadB extends Thread{ private MyList list; public ThreadB(MyList list){ super(); this.list = list; } @Override public void run(){ try{ synchronized(list){ if(list.size() != 5){ System.out.println("wait begin="+System.currentTimeMillis()); list.wait(); System.out.println("wait end="+System.currentTimeMillis()); } } }catch(InterruptedException e){ e.printStackTrace(); } } } public class RunDemo { public static void main(String[] args) { MyList run = new MyList(); try { ThreadB tB =new ThreadB(run); tB.setName("B"); tB.start(); Thread.sleep(500); ThreadA tA= new ThreadA(run); tA.setName("A"); tA.start(); } catch (InterruptedException e) { e.printStackTrace(); } } } wait begin=1516089526512 add item 1... add item 2... add item 3... add item 4... 已发出通知。 add item 5... add item 6... add item 7... add item 8... add item 9... add item 10... wait end=1516089537079
关键字synchronized可以将任何一个Object对象作为同步对象来看待,而Java为每一个Object都实现来wait和notify方法,它们必须用在被synchronized同步的Object临界区内。
方法wait锁释放与方法notify锁不释放,notify要在线程把程序所有代码执行完毕后才释放
interrupt方法不能在线程处于wait状态时使用,会报错
方法wait(long)
带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒