线程基础

生命周期

创建线程

实现 Runnable 接口

class MyRunnable implements Runnable {
    public void run() {
        // ...
    }
}

public static void main(String[] args) {
    MyRunnable instance = new MyRunnable();
    Thread thread = new Thread(instance);
    thread.start();
}

实现 Callable 接口

class MyCallable implements Callable<String> {
    public String call() {
        return "著作权归@pdai所有 原文链接:https://pdai.tech/md/java/thread/java-thread-x-thread-basic.html";
    }
}

public static void main(String[] args) throws ExecutionException, InterruptedException {
    MyCallable mc = new MyCallable();
    FutureTask<Integer> ft = new FutureTask<>(mc);
    Thread thread = new Thread(ft);
    thread.start();
    System.out.println(ft.get());
}

继承 Thread 类

class MyThread extends Thread {
    public void run() {
        // ...
    }
}

public static void main(String[] args) {
    MyThread mt = new MyThread();
    mt.start();
}

Thread 常用方法

方法 作用 描述
Thread() 创建线程 构造方法,有不同的构造方法,能多种形式创建线程
start() 启动线程 jvm 自动调用 run 方法
run() 线程的主体方法,定义线程的执行逻辑 不需要手动调用,jvm 自动调用
setName(String) | getName() 设置和获取线程名称
join() | join(millis) 线程插队 在 a 线程的 run 方法体中调用 b.join(),表示加入 b 线程,会等 b 线程执行完然后继续执行 a 线程
sleep(long millis) 线程休眠 让出 CPU ,不让出锁,时间到了再次抢夺 CPU(休眠期不会抢)
yield() 线程让步 让出 CPU ,不让出锁,可能让出 CPU 时间片后立马又被分配到了
currentThread() 获取当前线程

等待和唤醒

  1. wait:让出 cpu 时间片和 锁,程序走到这里立马暂停,既然要让处锁,所以必须先持有锁,所以必须用在 synchronized 中
  2. notify:唤醒正在等待 同一个锁 的线程,不是随便唤醒线程,而是等待同一个锁的线程,所以也必须用在 synchronized 中

notify 不会释放锁,要等到方法执行完才会释放锁

public class WaitNotifyExample {
    private final Object lock = new Object();
    private boolean condition = false;

    public void waitForCondition() throws InterruptedException {
        synchronized (lock) { 
            while (!condition) { // synchronized 中的判断不能用 if 要用 while
                System.out.println("让出 CPU 和锁.....");
                lock.wait(); // 等待条件为真
            }
            System.out.println("又抢到锁和分到 cpu 时间片...");
        }
    }

    public void setConditionTrue() {
        synchronized (lock) {
            condition = true;
            lock.notify(); // 唤醒一个等待线程(notify 不释放锁,但是这已是方法最后一行,方法结束会释放锁)
            // lock.notifyAll(); // 或者唤醒所有等待线程
        }
    }

    public static void main(String[] args) throws InterruptedException {
        WaitNotifyExample example = new WaitNotifyExample();

        Runnable waitTask = () -> {
            try {
                example.waitForCondition();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Thread thread1 = new Thread(waitTask);
        thread1.start();

        Thread.sleep(2000); // 等待2秒钟

        // 在主线程中设置条件为true,唤醒等待线程
        example.setConditionTrue();
    }
}

死锁

面试官:你告诉我什么是死锁我就录取你。候选人:你录取我我就告诉你什么是死锁

往往都是嵌套的 synchronized 导致

// 多运行几遍,如果效果不明显就两个线程获取第一把锁后分别 sleep 一会(两个线程获取的是不同的锁,第一次肯定都能获取)
public class DeadLockDemo {  
    // 两个锁
    private static String A="A";  
    private static String B="B";  
    
    public static void main(String[] args){  
        // 线程1
        new Thread(new Runnable(){  
            @Override  
            public void run(){  
                synchronized(A){  // 拿到 A 才进入
                    synchronized(B){  // 拿到 B 才进入(这时要同时具有 A 和 B)
                        System.out.println("AB");  
                    }  
                }  
            }  
        });
        
        // 线程2
        new Thread(new Runnable(){  
            @Override  
            public void run(){  
                synchronized(B){ 
                    synchronized(A){  // 这时要同时具有 A 和 B
                        System.out.println("BA");  
                    }  
                }  
            }  
        });
    } 
}
posted @   CyrusHuang  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示