多线程打印ABC

三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串。

  • if (idx == num)条件不满足时,锁会被释放,但线程会立即重新获取锁,导致忙等待(Busy Waiting),浪费CPU资源。
package Thread;
import java.util.concurrent.locks.ReentrantLock;
//三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串。
public class ABC {
    public static int count = 12;
    public static int idx = 0;
    static ReentrantLock reentrantLock = new ReentrantLock();
    public static void printABC(char c, int num){
        for(int i = 1; i <= count;){
            reentrantLock.lock();
            if(idx == num){
                idx = (idx + 1) % 3;
                i ++;
                System.out.print(c);
            }
            reentrantLock.unlock();
        }
    }
    public static void main(String[] args){
        Thread thread1 = new Thread(() -> printABC('A', 0));
        Thread thread2 = new Thread(() -> printABC('B', 1));
        Thread thread3 = new Thread(() -> printABC('C', 2));
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

改进版,使用通知进行线程之间的交互。

package Thread;
import java.util.concurrent.locks.ReentrantLock;

//三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串。
public class ABC {
    public static int count = 12;
    public static int idx = 0;
    static Object lock = new Object();//对象锁
    public static void printABC(char c, int num){
        for(int i = 1; i <= count; i ++){
            synchronized (lock){
                  //被唤醒也不一定是自己该打印
                while(idx != num){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.print(c);
                idx = (idx + 1) % 3;
                lock.notifyAll();//唤醒等待的线程,不包括自己
            }
        }
    }
    public static void main(String[] args){
        Thread thread1 = new Thread(() -> printABC('A', 0));
        Thread thread2 = new Thread(() -> printABC('B', 1));
        Thread thread3 = new Thread(() -> printABC('C', 2));
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

两个线程交替奇偶打印1-100

package Thread;

public class EvenAndOdd {
    public static int idx = 1;
    static Object lock = new Object();
    public static void printEven(boolean flag){
        int c = flag ? 1 : 0;
        while(true){
            synchronized (lock){
                while(idx % 2 != c){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                if(idx > 100) return;
                System.out.println(Thread.currentThread().getName() + " " + idx);
                idx ++;
                lock.notifyAll();
            }
        }
    }
    public static void main(String[] args){
        Thread thread1 = new Thread(() -> printEven(true));
        Thread thread2 = new Thread(() -> printEven(false));
        thread1.setName("even");
        thread2.setName("odd");
        thread1.start();
        thread2.start();
    }
}

生产者-消费者

例如一个厨子10s生产一个,一个客人4s消费一个。

package Thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class CustomerAndProducer {
    public static BlockingQueue<String> blockQueue = new ArrayBlockingQueue<>(100);
    public static class Producer implements Runnable{
        @Override
        public void run() {
            while(true){
                try {
                    Thread.sleep(10000);
                    blockQueue.add("food");
                    System.out.println("厨师放了一个餐品");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    public static class Consumer implements Runnable{
        @Override
        public void run() {
            while(true){
                try {
                    Thread.sleep(4000);
                    String food = blockQueue.take();
                    System.out.println("消费者消费了一个餐品");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    public static void main(String[] args){
        Thread thread1 = new Thread(new Producer());
        Thread thread2 = new Thread(new Consumer());
        thread1.start();
        thread2.start();
    }
}

单例模式:懒汉,饿汉,双重校验锁

懒汉

package Singleton;

public class Singleton {
    /*恶汉
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
    */
    /*懒汉
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
    }
    */
    // 使用 volatile 关键字确保 instance 的可见性
    private static volatile Singleton instance;
    // 私有构造函数,防止外部实例化
    private Singleton() {
        // 初始化代码
    }
    // 获取单例实例的静态方法
    public static Singleton getInstance() {
        // 第一次检查,避免不必要的同步
        if (instance == null) {
            // 加锁,确保线程安全
            synchronized (Singleton.class) {
                // 第二次检查,防止多个线程同时通过第一次检查
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

随机数

有一个0-4的随机器rand4,如何实现0-6的随机器rand6,概率相同。拓展:rand X = func(rand Y),实现func函数

Copyright © 版权信息 all right reserved,powered by aspire-zero and Gitbook该文件修订时间: 2025-03-04 11:27:21

results matching ""

    No results matching ""