实现线程同步有三种方法:
-
同步代码块
-
同步方法
-
Lock锁
以下用这三种方法模拟三个线程来卖票,实现共享票源
同步代码块:
package com.hucm.runnable;
public class RunSynImpl implements Runnable {
private int ticket = 100; //多线程共享的票源
Object obj = new Object(); //创建一个锁对象
@Override //设置线程任务卖票
public void run() {
while(true){
synchronized (obj){ //同步代码块 此处也可以写【this】
if (ticket > 0){
try {
Thread.sleep(10); //提高程序安全问题,让程序睡眠10ms
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->正在卖第" + ticket + "张票");
ticket--;
}
}
}
}
}
同步方法:
package com.hucm.runnable;
public class RunSynFunImpl implements Runnable{
private int ticket = 100;
@Override
public void run() {
while(true){
payTicket();
}
}
/*
* 定义一个同步方法,同步方法也会把方法内部的代码锁住
* 只让一个线程执行
*
* 同步方法的锁对象也就是实现类对象
*
* */
public synchronized void payTicket(){
if (ticket > 0) {
try {
Thread.sleep(10); //提高程序安全问题,让程序睡眠10ms
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->正在卖第" + ticket + "张票");
ticket--;
}
}
}
同步静态方法:
package com.hucm.runnable;
public class RunSynStaticImpl implements Runnable{
private static int ticket = 100;
@Override
public void run() {
while(true){
payTicketStatic();
}
}
/*
*
* 静态同步方法,他的锁对象【不是】this
* 因为this是创建对象之后产生,静态方法优先于对象
* 静态方法的锁对象是本类的class属性,即class文件对象(反射)
*
* */
public static void payTicketStatic(){
synchronized (RunSynStaticImpl.class){ //同步代码块 此处【不】可以写【this】
if (ticket > 0){
try {
Thread.sleep(10); //提高程序安全问题,让程序睡眠10ms
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->正在卖第" + ticket + "张票");
ticket--;
}
}
}
}
Lock锁:
package com.hucm.runnable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class RunLockImpl implements Runnable{
private int ticket = 100; //多线程共享的票源
Lock lock = new ReentrantLock(); //创建一个ReentrantLock对象
@Override //设置线程任务卖票
public void run() {
while(true){
lock.lock(); //有可能出现安全问题代码【前】调用Lock接口中的lock方法
if (ticket > 0){
try {
Thread.sleep(10); //提高程序安全问题,让程序睡眠10ms
System.out.println(Thread.currentThread().getName() + "-->正在卖第" + ticket + "张票");
ticket--;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock(); //有可能出现安全问题代码【后】调用Lock接口中的unlock方法
}
}
}
}
}
测试以上四种方法的测试类:
package com.hucm.runnable;
public class TestMain {
//创建三个线程同时开启,对共享的票进行出售
public static void main(String[] args) {
/*
* 创建了一个实现类,传到三个线程里面,为了保证票就是100张
*让三个线程来卖票,实现共享票源
* 如果创建了三个实现类,那么票就是300张,那就自个玩自个的
* */
// RunSynImpl run = new RunSynImpl(); //同步代码块
//RunSynFunImpl run = new RunSynFunImpl(); //同步方法
//RunSynStaticImpl run = new RunSynStaticImpl(); //静态同步方法
RunLockImpl run = new RunLockImpl(); //Lock锁
Thread t0 = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
//开启多线程
t0.start();
t1.start();
t2.start();
}
}