三种单例模式
饿汉式:一初始化就创建
class EagerSingleton {
private static EagerSingleton instance = new EagerSingleton();
private EagerSingleton()
{}
public static EagerSingleton getInstance()
{
return instance;
}
}
懒汉式:用的时候再创建
class LazySingleton {
private static LazySingleton instance =null;
private LazySingleton()
{
}
public static LazySingleton getInstance()
{
if(instance==null)
{
instance=new LazySingleton();
return instance;
}
return instance;
}
}
双重检查锁定 :双重检查锁定在懒汉式基础上优化,减少了同步的开销,保证了线程安全。
class DoubleCheckSingleton {
// volatile 关键字确保多线程环境下的可见性
private static volatile DoubleCheckSingleton instance =null;
private DoubleCheckSingleton()
{
}
public static DoubleCheckSingleton getInstance()
{
if(instance==null)
{
synchronized (DoubleCheckSingleton.class)
{
if(instance==null)
{
instance= new DoubleCheckSingleton();
}
}
}
return instance;
}
}
最后一个人的编号
多线程环境下避免竞态条件,加锁可以保证执行顺序
不加锁版本:
public class Counter {
// 记录当前的序号
private int count = 0;
// 增加计数并返回新的值
public synchronized int increment() {
count++;
return count;
}
// 获取当前计数值
public synchronized int getCount() {
return count;
}
public static void main(String[] args) {
Counter counter = new Counter();
// 创建多个线程,模拟多个“人”访问计数器
Runnable task = () -> {
for (int i = 0; i < 10; i++) {
int personNumber = counter.increment();
System.out.println("Person number: " + personNumber);
}
};
// 启动多个线程
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
Thread thread3 = new Thread(task);
thread1.start();
thread2.start();
thread3.start();
// 等待所有线程完成
try {
thread1.join();
thread2.join();
thread3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 输出最终的计数值
System.out.println("Final count: " + counter.getCount());
}
}
加锁版本
public class OrderedCounter {
private int count = 0;
private int threadId = 0;
private final int totalThreads;
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public OrderedCounter(int totalThreads) {
this.totalThreads = totalThreads;
}
public void increment(int id) {
lock.lock();
try {
while (id != threadId) {
condition.await();
}
count++;
System.out.println("Thread " + id + ": Person number: " + count);
threadId = (threadId + 1) % totalThreads;
condition.signalAll();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
int totalThreads = 3;
OrderedCounter counter = new OrderedCounter(totalThreads);
Runnable task1 = () -> {
for (int i = 0; i < 10; i++) {
counter.increment(0);
}
};
Runnable task2 = () -> {
for (int i = 0; i < 10; i++) {
counter.increment(1);
}
};
Runnable task3 = () -> {
for (int i = 0; i < 10; i++) {
counter.increment(2);
}
};
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
Thread thread3 = new Thread(task3);
thread1.start();
thread2.start();
thread3.start();
try {
thread1.join();
thread2.join();
thread3.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
交替打印奇数偶数
其实就是两个线程的理解,不停的等待与唤醒,交替持有锁,还成交替打印AB是一样的
public class AlternatingPrinter {
private static int count = 0;
private final Lock lock = new ReentrantLock();
private final int maxCount=100;
private final Condition condition =lock.newCondition();
public void printOdd() {
while (count <= maxCount) {
lock.lock();
try {
while (count % 2 == 0) {
condition.await();
}
if (count <= maxCount) {
System.out.println(Thread.currentThread().getName()+count);
count++;
condition.signalAll();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
lock.unlock();
}
}
}
public void printEven() {
while (count <= maxCount) {
lock.lock();
try {
while (count % 2 != 0) {
condition.await();
}
if (count <= maxCount) {
System.out.println(Thread.currentThread().getName()+count);
count++;
condition.signalAll();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
AlternatingPrinter alternatePrinter = new AlternatingPrinter();
Thread thread = new Thread(alternatePrinter::printOdd, "odd");
Thread thread2 = new Thread(alternatePrinter::printEven, "even");
thread.start();
thread2.start();
try {
thread.join();
thread2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
三个线程的交替打印:ABC
public class PrintABC {
private int maxtimes;
private final Lock lock = new ReentrantLock();
private final Condition condA = lock.newCondition();
private final Condition condB = lock.newCondition();
private final Condition condC = lock.newCondition();
public String status="A";
public PrintABC(int maxTimes) {
this.maxtimes=maxTimes;
}
public void printA()
{
for(int i=0;i<maxtimes;i++)
{
lock.lock();
try {
while(!status.equals("A"))
{
condA.await();;
}
System.out.println(Thread.currentThread().getName()+ "A");
status="B";
condB.signal();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
lock.unlock();
}
}
}
public void printB()
{
for(int i=0;i<maxtimes;i++)
{
lock.lock();
try {
while(!status.equals("B"))
{
condB.await();;
}
System.out.println(Thread.currentThread().getName()+ "B");
status="C";
condC.signal();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
lock.unlock();
}
}
}
public void printC()
{
for(int i=0;i<maxtimes;i++)
{
lock.lock();
try {
while(!status.equals("C"))
{
condC.await();;
}
System.out.println(Thread.currentThread().getName()+ "C");
status="A";
condA.signal();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
PrintABC printABC = new PrintABC(10);
Thread threada = new Thread(printABC::printA,"A线程");
Thread threadb = new Thread(printABC::printB,"B线程");
Thread threadc = new Thread(printABC::printC,"C线程");
threada.start();
threadb.start();
threadc.start();
try{
threada.join();
threadb.join();
threadc.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}