等待/通知机制(wait/notify机制)演示:
MyThreadA.java代码:
package cn.itcast.day06.demo4;
public class MyThreadA extends Thread{
private Object lock;//对象监视器
public MyThreadA(Object lock){
this.lock = lock;
}
@Override
public void run(){
try {
synchronized (lock){
System.out.println("开始wait,时间:" + System.currentTimeMillis());
lock.wait();
System.out.println("结束wait,时间:" + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
MyThreadB.java代码:
package cn.itcast.day06.demo4;
public class MyThreadB extends Thread{
private Object lock;//对象监视器
public MyThreadB(Object lock){
this.lock = lock;
}
@Override
public void run(){
synchronized(lock){
System.out.println("开始notify,时间:" + System.currentTimeMillis());
lock.notify();
System.out.println("结束notify,时间:" + System.currentTimeMillis());
}
}
}
Demo4.java代码:
package cn.itcast.day06.demo4;
import cn.itcast.day06.demo3.MyThread;
public class Demo4 {
public static void main(String[] args) {
try {
Object lock = new Object();//对象监视器
MyThreadA myThreadA = new MyThreadA(lock);
myThreadA.start();
Thread.sleep(3000);//主线程暂停3秒
MyThreadB myThreadB = new MyThreadB(lock);
myThreadB.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:特点:
1.Synchronized关键字可以使用任何一个Object对象作为对象监视器(同步对象),Java为每一个Object对象都实现了wait()方法和notify()方法。调用同步对象object的wait()方法和notify()方法必须在synchronized(object){...}所同步的代码块中。
2.调用object.wait()可以使当前线程进入等待状态,同时释放同步对象object的锁。
3.调用obejct.notify()可以随机唤醒等待队列中以object为同步对象的一个线程,让其退出等待队列,进入就绪状态。
4.object.notiy()方法只随机唤醒一个线程,而object.notifyAll()方法可以唤醒等待队列中所有以object对象为同步对象的线程。
5.执行wait()方法会立即释放锁,但是执行notify()方法不会立即释放锁,执行完后续代码才会释放锁。
线程状态切换示意图
通过管道实现线程间通信(pipe):
1.传递字节流使用PipedOutputStream和PipedInputStream;
2.传递字符流使用PipedWriter和PipedReader。
join()方法:
当子线程比较耗时,主线程执行的比较快,可能主线程结束了,子线程还没处理完任务。比如子线程用于处理数据,主线程需要获取子线程的处理结果,那么怎么让主线程确保子线程完成后,主线程拿到处理结果再结束呢,利用join()方法便可以实现。
package cn.itcast.day06.demo5;
public class MyThread extends Thread{
@Override
public void run(){
int n = (int) Math.random() * 1000;
System.out.println(n);
}
}
package cn.itcast.day06.demo5;
public class Demo5 {
public static void main(String[] args) {
try {
MyThread myThread = new MyThread();
myThread.start();
myThread.join();
System.out.println("在myThread运行结束后再打印出这句话!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ThreadLocal:
ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一乐ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题,如下图所示:使用代码演示:
package cn.itcast.day06.demo6;
public class ThreadLocalTest {
static ThreadLocal<String> threadLocal = new ThreadLocal<>();
}
package cn.itcast.day06.demo6;
public class Demo6 {
public static void main(String[] args) {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
ThreadLocalTest.threadLocal.set("threadA");
System.out.println("线程A设置的值为:" + ThreadLocalTest.threadLocal.get());
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
ThreadLocalTest.threadLocal.set("threadB");
System.out.println("线程B设置的值为:" + ThreadLocalTest.threadLocal.get());
}
});
threadA.start();
threadB.start();
}
}
运行结果