Java学习笔记——线程安全的3种实现方式

tech2023-08-15  83

先准备一个Ticket类

package simplecode; public class Ticket implements Runnable { private int ticket = 10; /* * 执行卖票操作 */ @Override public void run() { while (true) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //获取当前线程对象的名字 String name = Thread.currentThread().getName(); System.out.println(name + "正在卖:" + ticket--); } } } }

调用该类,会出现线程安全问题

package simplecode; public class ThreadSafeDemo { public static void main(String[] args) { //创建线程任务对象 Ticket ticket = new Ticket(); //创建三个窗口对象 Thread t1 = new Thread(ticket, "窗口1"); Thread t2 = new Thread(ticket, "窗口2"); Thread t3 = new Thread(ticket, "窗口3"); //同时卖票 t1.start(); t2.start(); t3.start(); } }

运行结果有可能是这样:

窗口2正在卖:10 窗口1正在卖:10 窗口3正在卖:9 窗口2正在卖:8 窗口1正在卖:6 窗口3正在卖:7 窗口2正在卖:5 窗口1正在卖:4 窗口3正在卖:3 窗口3正在卖:2 窗口1正在卖:1 窗口2正在卖:0 窗口3正在卖:-1

方式一:通过线程同步解决线程安全

package simplecode; public class Ticket implements Runnable { private int ticket = 10; private Object locker = new Object(); /* * 执行卖票操作 */ @Override public void run() { while (true) { synchronized (locker) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //获取当前线程对象的名字 String name = Thread.currentThread().getName(); System.out.println(name + "正在卖:" + ticket--); } } } } }

方式二:同步方法解决线程安全

package simplecode; public class Ticket implements Runnable { private int ticket = 10; /* * 执行卖票操作 */ @Override public void run() { while (true) { sellTickets(); } } public synchronized void sellTickets(){ if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //获取当前线程对象的名字 String name = Thread.currentThread().getName(); System.out.println(name + "正在卖:" + ticket--); } } }

方式三:同步锁解决线程安全

package simplecode; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Ticket implements Runnable { private int ticket = 10; private Lock locker = new ReentrantLock(); /* * 执行卖票操作 */ @Override public void run() { while (true) { locker.lock(); if (ticket > 0) { try { //获取当前线程对象的名字 String name = Thread.currentThread().getName(); System.out.println(name + "正在卖:" + ticket--); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }finally { locker.unlock(); } } } } }
最新回复(0)