直接步入正题:
1、若有一个方法需要实现多线程情况下一个一个访问,则可使用synchronized关键字来实现。
2、若有一个工作是需要用两个或多个线程来共同协作完成,并且必须是完成某个动作之后才能执行下一个动作,则可使用 wait() 和 notify() 结合来操作,也可使用volatile关键字来实现 ,也可以使用join()来实现。
举个栗子:
public class TestWait {
String name = "QQQ";//随意
volatile boolean flag = false;// volatile 关键字使flag线程之间可见
public synchronized void eat() {
System.out.println("当前线程ID:" + Thread.currentThread().getId() + ",在吃饭,等会吧");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前线程ID:" + Thread.currentThread().getId() + ",吃完了,下一位");
System.out.println("===============================================\n");
}
public void downAndShow() {
// 开启一个线程专门下载图片
new Thread(new Runnable() {
public void run() {
downLoad();
}
}).start();
// 开启一个线程专门显示图片
new Thread(new Runnable() {
public void run() {
show();
}
}).start();
}
public void downLoad() {
System.out.println("开始下载图片");
for (int i = 0; i < 101; i += 10) {
System.out.println("down" + i + "%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (name) {
name.notify();
}
System.out.println("图片下载成功");
}
public void show() {
synchronized (name) {
try {
name.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("展示图片");
}
}
public void volatileDownAndShow() {
// 开启一个线程专门下载图片
new Thread(new Runnable() {
public void run() {
volatileDownLoad();
}
}).start();
// 开启一个线程专门显示图片
new Thread(new Runnable() {
public void run() {
volatileShow();
}
}).start();
}
public void volatileDownLoad() {
System.out.println("开始下载图片");
for (int i = 0; i < 101; i += 10) {
System.out.println("down" + i + "%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = true;//设置flag为true,表示我已经把图片下载好了,剩下的交给你了兄弟
System.out.println("图片下载成功");
}
public void volatileShow() {
while (true) {//死循环,模拟自旋锁
if(flag){//因为flag 为volatile 所以在线程之间可见,线程1改变后,线程2也会随之改变
System.out.println("展示图片");
break;
}
}
}
public void JoinDownAndShow() throws InterruptedException {
// 开启一个线程专门下载图片
Thread thread1 = new Thread(new Runnable() {
public void run() {
JoinDownLoad();
}
});
// 开启一个线程专门显示图片
Thread thread2 = new Thread(new Runnable() {
public void run() {
JoinShow();
}
});
thread1.start();
thread1.join();// thread1调用join()方法,等到thread1执行完毕之后才执行下面操作
thread2.start();
}
public void JoinDownLoad() {
System.out.println("join() 方式 开始下载图片");
for (int i = 0; i < 101; i += 10) {
System.out.println("down" + i + "%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("图片下载成功");
}
public void JoinShow() {
System.out.println("展示图片");
}
}
编写测试类:
public class Test {
public static void main(String[] args) {
final TestWait tt = new TestWait();
//开始10个线程来模拟排队吃饭
// for(int i=0;i<10;i++){
// new Thread(new Runnable() {
// public void run() {
// tt.eat();
// }
// }).start();;
// }
// tt.downAndShow();
// tt.volatileDownAndShow();
tt.JoinDownAndShow();
}
}
结果展示:
1、排队吃饭示例:
2、wait() 和 notify() 实现下载图片后展示:
3、volatile方式实现下载图片后展示:
就酱。共勉