多线程基础第二篇

创建线程的方式

Java 提供了两种主要方法来创建线程:

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("继承 Thread 创建线程");
    }

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
    }
}
方法 2:实现 Runnable 接口

实现 Runnable 接口可以更灵活,因为 Java 不支持多继承,所以这种方式通常优于直接继承 Thread

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("实现 Runnable 接口创建线程");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start(); // 启动线程
    }
}

2. Thread 类的常用方法

start()
  • 用于启动线程。调用后,线程进入 就绪状态,等待 CPU 调度。
  • thread.start();
    
    run()
  • 定义线程的执行逻辑,但不直接调用它(直接调用不会创建新线程,必须通过 start() 运行)。
  • 让当前线程进入 休眠状态,暂停指定的毫秒数,然后再恢复到 就绪状态
  • sleep(long millis)
  • try {
        Thread.sleep(1000); // 暂停1秒
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    join()
  • 等待该线程执行完毕。可以用在主线程中等待子线程完成,以确保执行顺序。
  • Thread thread = new Thread(new MyRunnable());
    thread.start();
    thread.join(); // 主线程等待子线程执行完
    
    interrupt()isInterrupted()
  • interrupt() 方法用于打断一个线程的休眠或等待状态,发出一个中断信号。
  • isInterrupted() 用于检查线程是否已被中断。
  • thread.interrupt(); // 中断线程
    if (thread.isInterrupted()) {
        System.out.println("线程已中断");
    }
    
    getId()getName()setName()
  • 用于获取或设置线程的 ID 和名称。
  • getPriority() 和 setPriority(int priority)
    Thread 类有 3 种优先级常量:
    MIN_PRIORITY (1)
    NORM_PRIORITY (5)
    MAX_PRIORITY (10)
    
    
    thread.setPriority(Thread.MAX_PRIORITY); // 设置优先级为最大
    System.out.println("线程优先级: " + thread.getPriority());
    

    3. Thread 的生命周期和状态

    线程在执行过程中会经历多个状态,这些状态反映了线程的执行过程和进展情况:

  • NEW:线程创建后,但尚未调用 start()
  • RUNNABLE:线程已经启动,等待 CPU 调度执行。
  • BLOCKED:线程等待锁定资源而处于阻塞状态。
  • WAITING:线程处于等待状态,等待其他线程的通知。
  • TIMED_WAITING:线程在等待指定时间后被唤醒。
  • TERMINATED:线程完成执行或异常终止
4. yield()
yield() 方法可以让当前执行的线程放弃 CPU 资源,将其让给其他优先级相同或更高的线程。

5. 守护线程(Daemon Thread)

守护线程在后台运行,比如垃圾回收线程。设置一个线程为守护线程后,当所有非守护线程结束时,守护线程也会自动终止。

thread.setDaemon(true); // 设置为守护线程

6. 线程同步与锁机制

在多线程环境下,资源共享容易引发线程冲突。Java 提供了 synchronized 关键字来保证线程同步,避免数据不一致的问题。

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread t1 = new Thread(counter::increment);
        Thread t2 = new Thread(counter::increment);

        t1.start();
        t2.start();
    }
}

7. ThreadLocal

ThreadLocal 提供了线程内部的局部变量,每个线程有自己的独立副本。

public class ThreadLocalExample {
    private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            threadLocal.set(2);
            System.out.println("线程1的变量值: " + threadLocal.get());
        });

        Thread t2 = new Thread(() -> {
            System.out.println("线程2的变量值: " + threadLocal.get());
        });

        t1.start();
        t2.start();
    }
}

8. 使用线程池管理 Thread

在直接使用 Thread 时,由于缺少资源管理和线程重用,较难管理大量线程。通常通过 ExecutorService 线程池更好地管理 Thread 对象。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 5; i++) {
            executor.submit(() -> System.out.println(Thread.currentThread().getName() + " 执行任务"));
        }

        executor.shutdown();
    }
}

在 Java 中,Callable 通常和 ExecutorService 配合使用,通过 submit() 方法来执行,并返回一个 Future 对象,该对象用于获取线程执行的结果。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Callable<String> task = () -> {
            Thread.sleep(1000);
            return "任务完成";
        };

        Future<String> result = executor.submit(task);

        try {
            System.out.println("等待任务完成...");
            String output = result.get();  // 阻塞等待,直到结果返回
            System.out.println("任务结果: " + output);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        executor.shutdown();
    }
}
  • Future:可以通过 Future 来获取 Callable 的执行结果,result.get() 会阻塞主线程,直到 Callable 返回结果。
  • 异常处理Callable 支持抛出异常,能帮助捕获和处理任务中的错误。

相比之下,Callable 适合需要返回值或进行错误处理的多线程任务,而 Runnable 适用于不需要返

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值