多线程

线程创建

  • 创建一个Thread类,或者一个Thread子类的对象
  • 创建一个实现Runnable接口的类的对象

Thread类

Thread是一个线程类,位于java.lang包下

构造方法 说明
Thread() 创建一个线程对象
Thread(String name) 创建一个具有指定名称的线程对象
Thread(Runnable target) 创建一个基于Runnable接口实现类的线程对象
Thread(Runnable target,String name) 创建一个基于Runnable接口实现类,并且具有指定名称的线程对象

Thread常用方法

方法 说明
public void run() 线程相关的代码写在该方法中,一般需要重写
public void start() 启动线程的方法
public static void sleep(long m) 线程休眠m毫秒的方法
public final void join() 优先执行调用join()方法的线程
public final void join(long millis) 等待该线程终止的最长时间为millis毫秒
public static void sleep(long millis) 在指定的毫秒数内让正在执行的线程休眠(暂停执行)参数为休眠的时间,单位是毫秒

Runnable接口

  • 只有一个方法run()
  • Runnable是Java中用以实现线程的接口
  • 任何实现线程功能的类都必须实现该接口

为什么要实现Runnable接口?

  1. Java不支持多继承
  2. 不打算重写Thread类的基本方法

线程状态

  • 新建(New)
  • 可运行(Runnable)
  • 正在运行(Running)
  • 阻塞(Blocked)
  • 终止(Dead)

线程的生命周期

多线程_第1张图片

线程优先级

  • Java为线程类提供了10个优先级
  • 优先级可以用整数1-10表示,超过范围会抛出异常
  • 主线程默认优先级为5

优先级常量

  • MAX_PRIORITY:线程的最高优先级10
  • MIN_PRIORITY:线程最低优先级1
  • NORM_PRIORITY:线程的默认优先级5

优先级相关方法

方法 说明
public int getPriority() 获取线程优先级的方法
public void setPriority(int newPriority) 设置线程优先级的方法

线程同步问题

有以下一组代码:

Bank类

package bank;

public class Bank {
    private String account;
    private int balance;

    public Bank(String account, int balance) {
        this.account = account;
        this.balance = balance;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Bank [账号:"+account+" 余额:"+balance+"]";
    }

    //存款
    public void saveAccount(){
        //可以在不同位置处添加sleep方法
        //获取当前账号余额
        int balance = getBalance();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        balance += 100;
        setBalance(balance);
        System.out.println("存款后的账户余额为:"+balance);
    }

    public void drawAccount(){
        int balance = getBalance();
        balance = balance - 200;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        setBalance(balance);
        System.out.println("取款后的账户余额:"+balance);
    }
}

SaveAccount类:存钱的线程

package bank;

public class SaveAccount implements Runnable {
    Bank bank;
    public SaveAccount(Bank bank){
        this.bank = bank;
    }
    @Override
    public void run() {
        bank.saveAccount();
    }
}

DrawAccount类:取钱线程

package bank;
//取款
public class DrawAccount implements Runnable {
    Bank bank;
    public DrawAccount(Bank bank){
        this.bank = bank;
    }
    @Override
    public void run() {
        bank.drawAccount();
    }
}

Test类:测试类

package bank;

public class Test {

    public static void main(String[] args){
        Bank bank = new Bank("1001",1000);
        //创建线程对象
        SaveAccount sa = new SaveAccount(bank);
        DrawAccount da = new DrawAccount(bank);
        Thread save = new Thread(sa);
        Thread draw = new Thread(da);
        save.start();
        draw.start();
        try {
            draw.join();
            save.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(bank);
    }
}

这段代码存在以下的问题:

如果save线程中saveAccount方法运行完balance += 100;之后被draw线程抢占。

此时save线程中的balance已经+100,但是balance仍然是1000.此时draw线程开始执行drawAccount方法,程序将balance-200,并执行了setBalance方法,输出取款后的账户余额:800。

之后程序继续执行save线程中saveAccount剩下的方法setBalance()方法将balace设置为1100,输出存款后的账户余额为:1100。

就会得到以下的错误运行结果

多线程_第2张图片

为保持方法在同一个时间段内只有此方法执行,可以使用synchronized关键字。

  • 成员方法
  • public synchronized void saveAccount(){}
  • 静态方法
  • public static synchronized void saveAccount(){}
  • 语句块
  • synchronized(obj){}

修改后的代码:

Bank类

package bank;

public class Bank {
    private String account;
    private int balance;

    public Bank(String account, int balance) {
        this.account = account;
        this.balance = balance;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Bank [账号:"+account+" 余额:"+balance+"]";
    }

    //存款
    public synchronized void saveAccount(){
        //可以在不同位置处添加sleep方法
        //获取当前账号余额
        int balance = getBalance();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        balance += 100;
        setBalance(balance);
        System.out.println("存款后的账户余额为:"+balance);
    }

    public void drawAccount(){
        synchronized (this){
            int balance = getBalance();
            balance = balance - 200;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            setBalance(balance);
            System.out.println("取款后的账户余额:"+balance);
        }
    }
}

运行结果:
多线程_第3张图片

你可能感兴趣的:(java基础)