Java线程

Java多线程自定义类:

    • 继承Thread类,重写run()方法

    • 创建Thread类对象

    • 调用start()方法,启动后内部会执行run()方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class Test {
    public static void main(String[] args) {
    MyThread t1 = new MyThread();
    t1.start();
    for (int i = 0; i < 5; i++) {
    System.out.println("Main: "+i);
    }
    }
    }

    class MyThread extends Thread{
    @Override
    public void run(){
    for (int i = 0; i < 5; i++) {
    System.out.println("Subthread: "+i);
    }
    }
    }
    • 实现Runnable接口,重写run()方法
    • 使用Thread包装实现类的对象
    • 调用start()方法,启动后内部会执行run()方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class Test {
    public static void main(String[] args) {
    Runnable r = new MyRunnable();
    Thread t = new Thread(r);
    t.start();
    for (int i = 0; i < 5; i++) {
    System.out.println("Main: "+i);
    }
    }
    }

    class MyRunnable implements Runnable{
    @Override
    public void run(){
    for (int i = 0; i < 5; i++) {
    System.out.println("Subthread: "+i);
    }
    }
    }

    可以简化为匿名内部类的写法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Test {
    public static void main(String[] args) {
    Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 5; i++) {
    System.out.println("Thread output: "+i);
    }
    }
    });
    t.start();
    }
    }

    以及Lambda表达式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Test {
    public static void main(String[] args) {
    Thread t = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
    System.out.println("Thread output: " + i);
    }
    });
    t.start();
    }
    }
    • 实现Callable接口和FutureTask类(前两种run方法无法返回)
    • 定义一个类实现Callable接口,重写call方法,封装要做的事情和返回的数据
    • Callable类型的对象封装成FutureTask(线程任务对象)

线程的使用

Thread提供的常用方法 说明
public void run() 线程的任务方法
public void start() 启动线程
public String getName() 获取当前线程的名称,线程名称默认为Thread-索引
public void setName(String name) 为线程设置名称
public static Thread currentThread() 获取当前执行的线程对象
public static void sleep(long time) 让当前执行的线程休眠多少毫秒后,再继续执行
public final void join() 让调用该方法线程的线程先执行完毕

线程安全

多个线程同时操作同一个共享资源的时候,可能会出现业务安全问题。

线程同步的常见方案:加锁:每次只允许一个线程加锁,加锁后才能访问,访问完毕后自动解锁,然后其他线程才能再加锁进来

  • 同步代码块:把访问共享资源的核心代码上锁,保证线程安全

    1
    2
    3
    synchronized(同步锁){
    访问共享资源的代码
    }

    锁对象的使用规范:一般使用共享资源作为锁对象,对于实例方法使用this作为锁对象,对于静态方法建议使用字节码(类名.class)对象作为锁对象

  • 同步方法:把访问共享资源的核心方法上锁,保证线程安全

    1
    2
    3
    修饰符 synchronized 返回值类型 方法名称(形参列表){
    操作共享资源的代码
    }

    同步方法的锁默认存在

  • Lock锁:Lock为接口,可以采样实现类ReentrantLock来构建Lock锁对象

线程池

线程池时可以复用线程的技术。

创建新线程的开销较大,请求过多时,会产生大量的线程,严重影响系统性能。