就业班JavaSE第二阶段第6天
day06 【线程、同步】
--线程
Thread类
获取线程的名称:
使用Thread类中的方法getName()
String getName()返回该线程的名称
创建多线程程序的第一种方式:
创建Thread类的子类
步骤:
创建Thread类的子类
在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么),该run()方法的方法体就代表了线程需要完成的任务
创建Thread类的子类对象
调用Thread类中的方法start方法,java虚拟机调用该线程的run方法
void start()使该线程开始执行;java虚拟机调用该线程的run方法
结果是两个线程并发地执行;当前线程(main线程)和另外一个线程(创建的新线程,执行其run方法)
多次启动一个线程是非法的,特别是当线程已经结束执行后,不能再重新启动
Java程序属于抢占式调度,哪个线程的优先级高,哪个线程优先执行,同一个优先级,随机选择一个执行
创建多线程程序的第二种方法:
实现Runnable接口
步骤:
创建一个Runnable接口的实现类
在实现类中重写Runnable接口的run方法,设置线程任务
创建一个Runnable接口的实现类对象
创建Thread类对象,构造方法中传递Runnable接口的实现类对象
调用Thread类中的start方法啊,开启新的线程执行run方法
Thread和Runnable的区别:
匿名内部类方式实现线程的创建:
public class RunableImpTest02 {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
};
new Thread(runnable,"赵丽颖").start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
}
--线程安全
解决线程安全问题的一种方案:
使用同步代码块
格式:
synchronized(锁对象){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注意:
通过代码块中的锁对象,可以使用任意的对象
但是必须保证多个线程使用的锁对象是同一个
锁对象作用:、
把同步代码块锁住,只让一个线程在同步代码块中执行
同步技术的原理:
使用了一个锁对象叫同步锁,也叫对象锁,也叫对象监视器
同步中的线程,没有执行完毕不会释放锁,同步外的线程没有锁进不去同步
解决线程安全问题的第二种方案:
同步方法:
步骤:
吧访问了共享数据的代码抽取出来,放到一个方法中
在方法上添加syncharonized修饰符
格式:
修饰符 syncharonized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
定义一个同步方法
同步方法也会把方法内部的代码锁住
只让一个线程执行
同步方法的锁对象是谁?
就是实现类对象:new RunnableImp()
也就是this
解决线程安全问题的第三种方案:
Lock锁:
提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
public void lock() :加同步锁。
public void unlock() :释放同步锁。
步骤:
在成员位置创建一个ReentrantLock对象
在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
在可能会出现安全问题的代码后条用Lock接口中的方法unlock释放锁
--线程状态
NEW(新建): 线程刚被创建,但是并未启动。还没调用start方法。
Runnable(可运行):线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
Blocked(锁阻塞):当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
Waiting(无限等待):一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
Timed Waiting(计时等待):同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
Teminated(被终止):因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
Waiting(无限等待):
public class WaitingTest {
public static void main(String[] args) {
//创建锁对象,保证锁唯一
Object obj = new Object();
//消费者买包子线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "告知老板买包子");
//然后等待
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "开始吃包子");
}
}
}, "顾客").start();
//老板卖包子
new Thread(new Runnable() {
@Override
public void run() {
//老板做包子需要5秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//包子做好,唤醒顾客
synchronized (obj) {
obj.notify();
System.out.println(Thread.currentThread().getName() + "告知顾客包子做好了");
}
}
}, "老板").start();
}
}
|
|