一,线程安全问题的产生:简单总结,线程安全问题是由于多个线程对全局变量或者静态变量进行了写操作。
二,线程安全问题的处理:线程同步(Synchronized)
线程同步的两种方式:同步代码块,同步方法
synchronized(锁对象){
有出现对全局或静态变量执行写操作的代码
}
public synchronized void method{
可能会产生线程安全问题的代码
}
同步方法中的锁对象是this,而静态同步方法中的锁对象是 类名.class
三,等待与唤醒机制
目的:通过该机制,能使各个线程有效的利用资源
方法:wait() :等待,将正在执行的线程释放CPU执行权
notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒任意一个。
notifyAll():唤醒全部,唤醒线程池中被wait()的所有线程。
sleep()和wait()方法的区别
sleep: 不释放锁对象, 释放CPU使用权
在休眠的时间内,不能唤醒
wait(): 释放锁对象, 释放CPU使用权
在等待的时间内,能唤醒
代码实现:
注意细节问题:唤醒其他线程之后,在释放锁资源
import java.util.ArrayList;
class Product extends Thread{
private ArrayList<String> list;
public Product(ArrayList<String> list) {
this.list = list;
}
@Override
public void run() {
while(true) {
synchronized (list) {
if(list.size()<=0) {
for(int i =0;i<5;i++) {
String temp = "商品"+(i+1);
System.out.println(Thread.currentThread().getName()+"生产"+temp);
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add(temp);
}
list.notifyAll();
}else {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Customer extends Thread{
private ArrayList<String> list;
public Customer(ArrayList<String> list) {
this.list = list;
}
@Override
public void run() {
while(true) {
synchronized(list) {
while(list.size()>0) {
System.out.println(Thread.currentThread().getName()+"正在消费"+list.get(0));
list.remove(0);
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.notify();
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
Product product = new Product(list);
Customer customer = new Customer(list);
Customer customer2 = new Customer(list);
product.start();
customer.start();
customer2.start();
}
}