两个线程从初始化时,传入同一个对象,可发生通信。
使用static数据。
传入的参数可作为对象锁,多个线程竞争该对象锁。
1.使用wait/notify函数实现(等待/通知机制)
等待/通知机制
wait()使当前执行代码的线程进行等待,将该线程置入“等待队列中(随时唤醒可执行状态)”;调用wait方法前,必须获取到该对象的对象级别的锁(wait/notify方法继承与Object类),即只能在同步方法或者同步块中调用该方法。执行之后,释放对象锁,并且能和其他线程一起竞争该锁。
带参数wait(Long)方法等待某一段时间内是否有线程对锁进行唤醒,如果超过则自动唤醒,long后继续执行程序。
notify()同样需要获取对象锁才能在同步方法或者同步块中调用该方法。该方法会通知可能在等待该对象锁的其他线程,如果有多个则随机挑选一个。执行完notify之后,不会立即释放锁,wait中的线程也不能立即获取锁,要等到执行notify方法的线程将程序执行完,即退出synchronized代码块。notify唤醒其他wait线程,如果对象一直没有调用notify函数,即使对象处于空闲,锁已经释放,wait线程也只能一直处于等待,直到该对象调用notify/notifyAll
notify随机通知一个线程唤醒,进入可执行状态,多次调用则唤醒多个线程。
notifyAll使所有的wait状态线程从等待状态进入可执行状态,此时优先级最高的线程最先执行,也可能随机执行。取决于虚拟机的实现。
2.生产者,消费者模式实现
3.join方法实现
使调用join的线程对象执行完毕run方法中的任务之后,才执行当前线程任务:
public static void main(String[] args){
try{
MyThread myThread = new MyThread();
myThread.start();
myThread.join();
Sysotem.out.println("------主线程中的任务-----");
}catch(Exception e){
}
}
原本如果主线程中没有myThread.join(),输出函数也许会先于子线程执行完毕;加上join后,主线程将被无限期挂起,直到子线程执行完毕销毁后才继续执行。阻止被插入的线程的执行,先执行插入的线程。
join(Long),设置等待的时间,内部采用wait(Long)实现,具有释放锁的特点,所以调用之后会释放锁。
sleep(Long),也会等待再执行,不会释放锁。
4.ThrealLocal实现
ThreadLocal解决每一个线程都能绑定自己的值。存放着每个线程的私有数据。
public static ThreadLocal tl = new ThreadLocal()
tl.get()取值,默认第一次调用没有值返回null。可以继承ThreadLocal类,重写initailValue()方法,返回初始值。
tl.set()存值
哪个线程调用ThreadLocal对象及其函数,则对该线程的数据进行操作。main线程调用,操作main线程数据,若是在ThreadA线程的run中调用,则是操作A线程的数据。
使用InheritableThreadLocal类在让子线程从父线程中获取值,例如在main函数中创建新的进程,新的进程的run函数中调用InheritableThreadLocal对象,get函数获取main线程的数据。