Java 线程常用操作

🚀 优质资源分享 🚀

学习路线指引(点击解锁)知识定位人群定位
🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

继Java线程生命周期继续学习Java线程其他常用操作

线程的常用操作

设置线程名字:setName()

获取线程名称:getName()

线程唯一Id:getId()

// 自定义线程名称
String threadName = "threadName";
// 构造方法方式
Thread thread = new Thread(() -> {
    System.out.println("线程名=" + Thread.currentThread().getName());
},threadName);
// set方法方式// thread.setName(threadName);
System.out.println("线程唯一Id=" + thread.getId());

线程启动:start()

判断线程是否存活:isAlive()

// 线程启动
thread.start();
System.out.println("是否为存活线程=" + thread.isAlive());

线程方法:run() /call()

线程启动后会去调用的方法。线程要做什么就在run/call方法写,不需要直接调用,线程启动后自己会去调用run() /call()。如果程序没有启动线程直接调用run/call,那么就不属于多线程编程,是属于当前线程直接调用普通方法一样。

获取当前线程对象:currentThread()

操作当前线程的非static方法,得先拿到线程对象才可以

// 获取当前线程对象
Thread currentThread = Thread.currentThread();
// 对当前线程做一些操作
System.out.println(currentThread.getName());
try {
    // sleep 静态方法则不需要
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

关于线程的状态控制(生命周期)的操作可以参考上一篇文章。

守护线程(后台线程)

普通线程(用户线程)的守护者,守护线程的任务是为其他的线程提供服务。如果进程中没有了用户线程,那么守护线程也就没有存在的意义,JVM也随之结束。典型的守护线程有JVM的垃圾回收线程,操作系统的启动也会启动各种模块的守护线程。

设置线程为守护线程:setDaeman()

注意:该方法必须在start() 方法之前调用

public static void main(String[] args) {
    Thread thread = new Thread(() -> {
        System.out.println("线程名="+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 这一句不会打印出来,因为main线程(目前唯一的普通线程)等待1秒后已经结束了
        System.out.println("守护线程的状态=" + Thread.currentThread().getState());
    });
    // 守护线程
    thread.setDaemon(true);
    // 线程启动
    thread.start();
    System.out.println("是否为守护线程=" + thread.isDaemon());
}

线程串行化

执行join() 方法的线程进入等待唤醒状态(WAITING),直到调用该方法的线程结束后再由等待唤醒状态转为可运行状态(RUNNABLE)。join() 方法是Thread类中的方法,其底层是使用wait() 方法来实现线程等待,待线程isAlive()为false 时才

实现线程的串行化:一个线程调用另一个线程对象的join() 来实现线程串行化执行。

举个例子:一道好菜

public class DemoCooking {
    
    public static void main(String[] args) {
        Thread mainThread = Thread.currentThread();
        // 1.买菜
        Thread buyThread = new Thread(new CookingThread(mainThread,"买菜"),"buyThread");
        // 2.洗菜
        Thread washThread = new Thread(new CookingThread(buyThread,"洗菜"),"washThread");
        // 3.切菜
        Thread cutThread = new Thread(new CookingThread(washThread,"切菜"),"cutThread");
        // 4.炒菜
        Thread scrambleThread = new Thread(new CookingThread(cutThread,"炒菜"),"scrambleThread");

        // 不受线程启动顺序的影响
        scrambleThread.start();
        washThread.start();
        cutThread.start();
        buyThread.start();
        
        // main线程先执行完才可以开始:买菜
        System.out.println("开始准备……");
    }

    public static class CookingThread implements Runnable{
        private final Thread thread;
        private final String job;

        public CookingThread(Thread thread, String job){
            this.thread = thread;
            this.job = job;
        }
        @Override
        public void run() {
            String name = Thread.currentThread().getName()+":";
            try {
                thread.join();

                System.out.println(name + job + "开始");
                Thread.sleep(1000);
                System.out.println(name + job + "结束");
                Thread.sleep(1000); // 偷懒下
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

执行结果:main > buyThread > washThread > cutThread > scrambleThread > 结束

开始准备……

buyThread:买菜开始

buyThread:买菜结束

washThread:洗菜开始

washThread:洗菜结束

cutThread:切菜开始

cutThread:切菜结束

scrambleThread:炒菜开始

scrambleThread:炒菜结束

线程优先级

设置当前线程的优先级,线程优先级越高,线程可能获得执行的次数越多,Java线程的优先级用整数表示,优先级的范围为1-10,默认为5。

setPriority(int)方法:设置线程的优先级。

getPriority方法:获取线程的优先级。

public static void main(String[] args) {

    Thread thread = new Thread(() -> {
        System.out.println("线程1");
    });
    thread.setPriority(10);
    Thread thread1 = new Thread(() -> {
        System.out.println("线程2");
    });
    thread1.setPriority(1);
    thread.start();
    thread1.start();

    System.out.println("线程默认的优先级为=" + Thread.currentThread().getPriority());

}

线程中断

使用interrupt() 方法设置线程中断标志=true,让线程受到“阻塞”时抛出一个中断信号。如果线程处于阻塞、等待唤醒或超时等待状态(Object.wait, Thread.join和Thread.sleep)时,那么它将接收到一个中断异常(InterruptedException),从而提前被结束该状态。反之,如果线程是处于“可运行”(RUNNABLE)状态,那么中断标志将没有作用。

案例一:线程中断有效

public static void main(String[] args) {
    Thread thread = new Thread(() -> {
        System.out.println("线程1");
        try {
            // 闹钟1分钟后响
            Thread.sleep(60000);
            System.out.println("闹钟响了");
        } catch (InterruptedException e) {
            // 提前退出超时等待状态
            System.out.println("发生异常,提前醒了,闹钟没响手动关了");
        }

        System.out.println("继续执行该线程的后续程序……");

    });
    thread.setPriority(1);
    thread.start();
    thread.interrupt();
    System.out.println("main线程将thread 终端状态设置为 "+thread.isInterrupted());
}

执行结果:

main线程将thread 终端状态设置为 true

线程1

发生异常,提前醒了,闹钟没响手动关了

继续执行该线程的后续程序……

案例二:线程中断无效

public static void main(String[] args) {
    Thread thread1 = new Thread(() -> {
        System.out.println("线程" + Thread.currentThread().getName());
        while (true) {
            System.out.print(Thread.currentThread().getState() + "\t");
        }
    });
    thread1.start();
    thread1.interrupt();
}

执行结果:线程一直打印自己的状态为RUNNABLE。

image

自己编写平滑加权轮询算法,实现反向代理集群服务的平滑分配

Java实现平滑加权轮询算法–降权和提权

Java实现负载均衡算法–轮询和加权轮询

Java往期文章

Java全栈学习路线、学习资源和面试题一条龙

我心里优秀架构师是怎样的?

免费下载经典编程书籍

更多优质文章,请关注WX公众号:Java全栈布道师

image

<think> 首先,用户查询是:“我想查找Java线程常用类的相关信息”,意思是“I want to find information about commonly used classes for Java multithreading”。用户提供了几个引用:[^1], [^2], [^3], [^4],这些引用包含了Java线程相关的代码示例和描述。 根据系统级指令: - 所有行内数学表达式使用$...$格式,但目前没有数学内容,所以可能不需要。 - 独立公式用$$...$$,但主题是Java线程,没有数学公式。 - LaTeX语法正确:这里主要是代码和文本,不需要LaTeX数学。 - 使用中文回答:整个回答必须是中文。 - 生成相关问题:在回答末尾添加相关问题。 - 引用的段落末尾自然地添加引用标识:如[^1]。 用户引用的内容: - [^1]: 讨论了使用Semaphore解决线程安全问题,示例代码使用Semaphore来同步两个线程递增计数器。 - [^2]: 讨论了CountDownLatch,用于等待多个线程完成。 - [^3]: 讨论了使用线程池(ExecutorService)和实现Runnable接口,示例是异步记录日志。 - [^4]: 提到了ReentrantLock,使用tryLock()尝试获取锁。 用户的核心问题是关于Java线程常用类。所以,我需要基于这些引用,总结Java线程常用的类和工具。 常见的Java线程类: - Semaphore:用于控制对共享资源的访问,通过许可证。 - CountDownLatch:用于等待其他线程完成。 - ReentrantLock:提供更灵活的锁定机制。 - ExecutorService:线程池框架,用于管理线程。 - Runnable:接口用于定义任务。 - Thread:基础线程类。 - 其他如CyclicBarrier、Phaser等,但引用中没有提到。 基于引用: - [^1]:Semaphore - [^2]:CountDownLatch - [^3]:ExecutorService和Runnable - [^4]:ReentrantLock 我应该结构化回答: 1. **介绍**:简要说明Java线程常用类的重要性。 2. **详细类**:逐一介绍每个常用类,包括: - 类名和作用 - 简要解释 - 示例代码片段(基于引用) - 添加引用标识 3. **总结**:归纳这些类的用途。 4. **相关问题**:生成相关问题。 回答结构: - 清晰、逐步解决问题。 - 尽量真实可靠,基于提供的引用。 最终输出格式: - 中文。 - 引用标识在相关段落末尾。 - 代码块用代码格式。 - 末尾添加§§相关问题§§部分。 列出要覆盖的类: 1. Semaphore (from [^1]) 2. CountDownLatch (from [^2]) 3. ExecutorService and Runnable (from [^3]) 4. ReentrantLock (from [^4]) 每个类描述: - 作用 - 关键方法 - 代码示例(简化或直接从引用中取) 生成相关问题: - 基于常见问题,如性能、优化、应用场景。 完整回答大纲: 1. 开头:介绍Java线程常用类,如并发工具类。 2. Semaphore:解释,代码示例,引用[^1]。 3. CountDownLatch:解释,代码示例,引用[^2]。 4. ExecutorService and Runnable:解释,代码示例,引用[^3]。 5. ReentrantLock:解释,代码示例,引用[^4]。 6. 总结。 7. 相关问题。 </think> ### Java线程常用类介绍 在Java中,多线程编程依赖于java.util.concurrent包(简称JUC)提供的工具类,这些类旨在简化线程同步、通信和管理任务。这些类高效解决并发问题,避免手动管理线程锁带来的复杂性。以下基于您提供的引用内容,总结常用类及其核心用法。我将逐一介绍每个类的作用、关键方法和代码示例,并确保描述真实可靠,引用来源末尾标明。 #### 1. **Semaphore(信号量)** Semaphore用于控制对共享资源的访问数量,通过许可证机制实现线程同步。常用于限流或资源池管理。 - **作用**:限制同时访问资源的线程数,acquire()获取许可证(加锁),release()释放许可证(解锁)。 - **关键方法**:acquire(), release()。 - **代码示例**(基于引用[^1]): ```java import java.util.concurrent.Semaphore; public class ThreadDemon40 { private static int count = 0; private static Semaphore semaphore = new Semaphore(1); // 初始化信号量,允许1个线程访问 public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { try { semaphore.acquire(); // 加锁 for (int i = 1; i <= 50000; i++) { count++; } } catch (InterruptedException e) { e.printStackTrace(); } semaphore.release(); // 解锁 }); Thread t2 = new Thread(() -> { try { semaphore.acquire(); // 加锁 for (int i = 1; i <= 50000; i++) { count++; } } catch (InterruptedException e) { e.printStackTrace(); } semaphore.release(); // 解锁 }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(count); // 输出安全递增后的计数 } } ``` 此示例确保count++操作线程安全,避免竞态条件[^1]。 #### 2. **CountDownLatch(倒计时门闩)** CountDownLatch用于等待多个线程完成任务后再继续主线程,类似“大号join”。常用于并行任务协调。 - **作用**:初始化一个计数器(如N个线程),每个线程完成时调用countDown()减少计数,主线程通过await()阻塞等待所有线程结束。 - **关键方法**:await(), countDown()。 - **代码示例**(基于引用[^2]): ```java import java.util.Random; import java.util.concurrent.CountDownLatch; public class Test { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(10); // 初始化计数器为10 Runnable runnable = new Runnable() { @Override public void run() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println(Thread.currentThread().getName() + "到达终点"); latch.countDown(); // 计数器减1 } catch (InterruptedException e) { e.printStackTrace(); } } }; for (int i = 0; i < 10; i++) { Thread t = new Thread(runnable, "运动员" + (i+1)); t.start(); } latch.await(); // 主线程阻塞,直到计数器归零 System.out.println("比赛结束"); } } ``` 此代码模拟10个运动员比赛,主线程在全部线程完成后输出“比赛结束”[^2]。 #### 3. **ExecutorService(线程池)和Runnable** ExecutorService管理线程池,避免频繁创建销毁线程的开销;Runnable接口定义任务逻辑。常用于异步任务执行。 - **作用**:ExecutorService提交任务(submit()或execute()),Runnable实现run()方法定义具体任务。 - **关键方法**:execute(Runnable), shutdown()。 - **代码示例**(基于引用[^3]): ```java public class LoggingThread implements Runnable { private String logMessage; public LoggingThread(String logMessage) { this.logMessage = logMessage; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ": " + logMessage); } public static void main(String[] args) { // 使用线程池执行Runnable任务 java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(2); executor.execute(new LoggingThread("User login succeeded")); executor.execute(new LoggingThread("File uploaded")); executor.shutdown(); // 关闭线程池 } } ``` 此示例使用线程池异步记录日志,提高资源利用率[^3]。 #### 4. **ReentrantLock(可重入锁)** ReentrantLock提供更灵活的锁机制,优于synchronized关键字,支持尝试获取锁(tryLock)。 - **作用**:通过lock()加锁,unlock()解锁;tryLock()非阻塞尝试获取锁。 - **关键方法**:lock(), unlock(), tryLock()。 - **代码示例**(基于引用[^4]): ```java import java.util.concurrent.locks.ReentrantLock; public class LockExample { private static final ReentrantLock lock = new ReentrantLock(); private static int resource = 0; public static void main(String[] args) { Thread t1 = new Thread(() -> { if (lock.tryLock()) { // 尝试获取锁 try { resource += 1; System.out.println("Thread 1 updated resource"); } finally { lock.unlock(); // 解锁 } } else { System.out.println("Thread 1 failed to acquire lock"); } }); Thread t2 = new Thread(() -> { lock.lock(); // 阻塞获取锁 try { resource += 2; System.out.println("Thread 2 updated resource"); } finally { lock.unlock(); } }); t1.start(); t2.start(); } } ``` 此示例展示tryLock()的非阻塞特性,提高线程灵活性[^4]。 ### 总结 Java线程常用类包括: - **同步工具**:Semaphore(资源访问控制)、CountDownLatch(线程等待)和ReentrantLock(灵活锁机制)。 - **任务管理**:ExecutorService(线程池)和Runnable(任务定义)。 这些类简化了并发编程,推荐优先使用JUC工具类替代原始线程操作,以提高性能和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值