卖票:
代码如下
public class SellTicket implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true){
if (ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" is selling the "+ticket+"ticket.");
ticket--;
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st = new SellTicket();
Thread t1 = new Thread(st,"1");
Thread t2 = new Thread(st,"2");
Thread t3 = new Thread(st,"3");
System.out.println("mmm");
t1.start();
t2.start();
t3.start();
}
}
启动三个线程来卖票,ticket是共享数据。结果不仅出现了重复的票,还出现了负数票。
ticket是成员变量。
如何解决线程安全的问题:
加上synchronized锁:
public class SellTicket implements Runnable {
private int ticket = 100;
private Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is selling the " + ticket + "ticket.");
ticket--;
}
}
}
}
}
以上是使用同步代码块,也可以使用同步方法。
同步方法和同步静态方法的总结:
ctrl+b: 跳到源代码
线程安全的类:
StringBuffer线程安全,StringBuilder线程不安全
Lock锁:
在java.util.concurrent.locks包下
使用finally来确保一定会释放锁
public class SellTicket implements Runnable {
private int ticket = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try{
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is selling the " + ticket + "ticket.");
ticket--;
}
} finally {
lock.unlock();
}
}
}
}
生产者和消费者模式:
用送奶工(生产者),奶盒(共享数据),顾客(消费者)来做例子:
public class Box {
private int milk;
private boolean state;
public synchronized void put(int milk){
//有奶,等待消费
if (state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//无奶,生产
this.milk = milk;
System.out.println("The producer puts "+milk+"bottle of milk into the box");
state = true;
notifyAll();
}
public synchronized void get() {
if (!state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("The customer takes "+milk+"bottle of milk");
state=false;
notifyAll();
}
}
public class Produer implements Runnable {
Box b;
public Produer(Box b) {
this.b = b;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
b.put(i);
}
}
}
public class Customer implements Runnable{
Box box;
public Customer(Box box) {
this.box = box;
}
@Override
public void run() {
while (true){
box.get();
}
}
}
public class BoxDemo {
public static void main(String[] args) {
Box box = new Box();
Produer p = new Produer(box);
Customer c = new Customer(box);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
输出结果: