Java学习笔记:多线程和线程同步

60 阅读2分钟

一、多线程的几种实现方式:

  • 使用Thread类

   1. 定义一个java.lang.Thread的子类,必须重写其中的run方法:

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(this.getName()); // 打印线程名称
    }
}

2. 在需要的地方,创建一个子类对象,并调用该对象的start方法:

public class testDemo {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}
  • 使用Runnable接口

  1. 定义一个Runnable接口的实现类,实现接口中的run方法:

public class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()); // 打印线程名称
    }
}

  2. 可以匿名创建一个Thread对象,传入一个实现Runnable接口的对象,再调用start方法:

public class testDemo {
    public static void main(String[] args) {
        Runnable thread = new MyThread();
        new Thread(thread).start();
    }
}
  • 使用匿名内部类的方式创建新的线程

  --> 用于一次性使用的情况,避免创建一个新的类:

public class testDemo {
    public static void main(String[] args) {
        new Thread() {
            // 在匿名内部类中重写run方法
            @Override
            public void run() {
                System.out.println(this.getName()); // 打印线程名称
            }
        }.start();
    }
}

二、线程同步的几种实现方式:

    在使用多线程时,为了线程安全,我们一般需要对部分代码进行同步处理,以下是Java中实现线程同步的几种方式:

    注意以下几种实现方式的锁对象必须是唯一的!

  • 使用同步代码块

  通过synchronized关键字,传入一个锁对象,可实现同步代码:

public void run() {
    // 此处需要传入一个锁对象,可以是this,也可以专门创建一个成员变量Object作为锁对象
    synchronized (this) {
        System.out.println("Thread Started");
    }
}
  • 使用同步方法

  把需要实现同步的代码整合到一个方法中,再用synchronized来修饰这个方法:

@Overridepublic void run() {
    this.myMethod();
}
public synchronized void myMethod(){ // 添加一个synchronized关键字
    System.out.println(Thread.currentThread().getName());
}
  • 使用Lock接口的实现类ReentrantLock类

  即在同步代码执行前后分别给代码加锁解锁:

public class MyThread implements Runnable {
    Lock l = new ReentrantLock();
    @Override
    public void run() {
        l.lock(); // 同步代码执行前锁住进程
        System.out.println(Thread.currentThread().getName());
        l.unlock(); // 同步代码执行后解锁进程
    }
}

  官方推荐使用try...catch...finally的写法:

public class MyThread implements Runnable {
    Lock l = new ReentrantLock();
    @Override
    public void run() {
        l.lock(); // 同步代码执行前锁住进程
        try {
            System.out.println(Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace(e);
        } finally { // finally中的代码必定会执行,无论代码是否出现异常,锁对象都能释放掉
            l.unlock(); // 同步代码执行后解锁进程
        }
    }
}