线程创建
- 创建一个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接口?
- Java不支持多继承
- 不打算重写Thread类的基本方法
线程状态
- 新建(New)
- 可运行(Runnable)
- 正在运行(Running)
- 阻塞(Blocked)
- 终止(Dead)
线程的生命周期
线程优先级
- 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。
就会得到以下的错误运行结果
为保持方法在同一个时间段内只有此方法执行,可以使用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);
}
}
}
运行结果: