一、处理多线程的步骤
- 确定同步前提
- 用synchronized解决安全问题
- 用线程通信解决逻辑顺序
二、有关锁的问题
wait和notify的理解是对共享资源的锁的管理,而不是对线程的管理。
因此wait和notify必须在拥有锁的线程中使用,即在synchronized修饰的代码块中使用。
三、多线程的处理实践
两个思路,一是在主线程中处理同步,二是在资源文件中处理同步。
在线程中处理同步:
public class CommunicateTread {
public static void main(String[] args) {
Res res = new Res("木木", "男");
new Thread(new Input(res)).start();
new Thread(new Output(res)).start();
}
}
class Input implements Runnable {
private Res res;
private int i;
public Input(Res res) {
this.res = res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
if (res.flag) {
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (i == 0) {
res.name = "呆呆";
res.sex = "女";
} else {
res.name = "木木";
res.sex = "男";
}
res.flag = true;
res.notify();
}
i = ++i % 2;
}
}
}
class Output implements Runnable {
private Res res;
public Output(Res res) {
this.res = res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
if(!res.flag){
try {
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("此时name为 " + res.name + " sex为 " + res.sex);
res.flag = false;
res.notify();
}
}
}
}
class Res {
//此标志为需求逻辑上的标记,不可和对象锁混淆。
boolean flag;// true 为为打印,false 为可修改
String name;
String sex;
public Res(String name, String sex) {
this.name = name;
this.sex = sex;
}
}
优化,对资源存取方式处理同步,重写Res,Input,Output类:
代码略,见下文生产消费者代码。
#### 四、经典的生产者消费者
1、两个线程,一个为生产者,一个为消费者。
2、多个线程,if判断标记 改为 while循环一直在检测标志;notify改为notifyAll。
package thread;
public class ClassicalThread {
public static void main(String[] args) {
Resourse res = new Resourse();
new Thread(new Producer(res)).start();
new Thread(new Producer(res)).start();
new Thread(new Producer(res)).start();
new Thread(new Resumer(res)).start();
new Thread(new Resumer(res)).start();
new Thread(new Resumer(res)).start();
}
}
class Resourse {
private String name;
private int id = 0;
private boolean flag = true;
public synchronized void produce(String name) {
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
System.out.println("生产" + name + " " + ++id);
flag = false;
notifyAll();
}
public synchronized void resume() {
while (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费" + name + " " + id);
flag = true;
notifyAll();
}
}
class Producer implements Runnable {
private Resourse res;
public Producer(Resourse res) {
this.res = res;
}
@Override
public void run() {
while (true) {
res.produce("商品");
}
}
}
class Resumer implements Runnable {
private Resourse res;
public Resumer(Resourse res) {
this.res = res;
}
@Override
public void run() {
while (true) {
res.resume();
}
}
}
“`