线程状态
线程状态 导致状态发生条件
NEW(新建) 线程刚被创建,但是并未启动。还没调用start方法。
Runnable(可运行)
线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操
作系统处理器。
Blocked(锁阻塞)
当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状
态;当该线程持有锁时,该线程将变成Runnable状态。
Waiting(无限等待)
一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个
状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
TimedWaiting(计时等待)
同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态
将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、
Object.wait。Teminated(被终止)
因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
两个不同线程操作同一个资源
使用同步来完成,锁使用共享的资源对象,但会造成线程阻塞,同一时间段只会输出同一输入,无法做到输出当时输入的
线程间通信的方法
wait():调用了 wait()方法的线程进入等待池进行等待,等待
池中的线程不去竞争对象锁,直到其它的线程通知,才会进入
锁池
notify():随机唤醒一个在该对象上等待的线 程,被唤醒的线
程进行锁池,开始竞争该对锁上的锁
notifyAll():唤醒所有在该对象上等待的线程
优先级高的线程有可能先竞争到对象锁
只能在同步方法和同步代码块中使用
//Resource
public class Resource {
String name;
String sex;
}
//Input
public class Input implements Runnable{
Resource r;
public Input(Resource r) {
this.r = r;
}
@Override
public void run() {
int x=0;
while(true){
synchronized (r){
if(x==0){
r.name="yk";
r.sex="male";
}else{
r.name="kk";
r.sex="female";
}
}
x=(x+1)%2;
}
}
}
//Output
public class Output implements Runnable{
Resource r;
Output(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
synchronized (r){
System.out.println(r.name+"...."+r.sex);
}
}
}
}
//main
Resource r = new Resource();
Input in = new Input(r);
Output ot = new Output(r);
Thread tInput = new Thread(in);
Thread tOutput = new Thread(ot);
tInput.start();
tOutput.start();
等待唤醒
- wait():让线程处于冻结状态,释放CPU执行权和执行资格,会被存储到线程池中
- notify():唤醒线程池中任意一个线程,具备执行资格
- notifyAll():唤醒线程池中所有线程
这些方法必须在同步代码中,因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程
都是定义在Object中,所以要用锁对象来调用,作为监视器
调用wait和notify方法需要注意的细节
- wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程。
- wait方法与notify方法是属于Object类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的。
- wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方法。
//Resource
public class Resource {
String name;
String sex;
boolean flag=false;
}
//Input
public class Input implements Runnable{
Resource r;
public Input(Resource r) {
this.r = r;
}
@Override
public void run() {
int x=0;
while(true){
synchronized (r){
if(r.flag){
try {
r.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(x==0){
r.name="yk";
r.sex="male";
}else{
r.name="kk";
r.sex="female";
}
r.flag=true;
r.notify();
}
x=(x+1)%2;
}
}
}
//Output
public class Output implements Runnable{
Resource r;
Output(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
synchronized (r){
if(!r.flag){
try {
r.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(r.name+"...."+r.sex);
r.flag=false;
r.notify();
}
}
}
}
//main
Resource r = new Resource();
Input in = new Input(r);
Output ot = new Output(r);
Thread tInput = new Thread(in);
Thread tOutput = new Thread(ot);
tInput.start();
tOutput.start();
代码优化,输入,输出函数放入对象中
//Resource
public class Resource {
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
this.sex = sex;
flag=true;
this.notify();
}
public synchronized void out(){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+"...."+sex);
flag=false;
this.notify();
}
}
//Input
public class Input implements Runnable{
Resource r;
public Input(Resource r) {
this.r = r;
}
@Override
public void run() {
int x=0;
while(true){
synchronized (r){
if(x==0){
r.set("yk","male");
}else{
r.set("kk","female");
}
}
x=(x+1)%2;
}
}
}
//Output
public class Output implements Runnable{
Resource r;
Output(Resource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.out();
}
}
}
//main
Resource r = new Resource();
Input in = new Input(r);
Output ot = new Output(r);
Thread tInput = new Thread(in);
Thread tOutput = new Thread(ot);
tInput.start();
tOutput.start();
生产者 消费者
1,持有锁
2,判断业务条件是否满足,若不满足则等待
3,唤醒在此监视器上的线程
多生产多消费
//RoastDuck
public class RoastDuck {
private String name;
private int count = 1;
private boolean flag=false;
public synchronized void produce(String name){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
count++;
System.out.println("producer..."+Thread.currentThread().getName()+"..."+this.name);
flag=true;
notifyAll();
}
public synchronized void consume(){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("consumer..."+Thread.currentThread().getName()+"..."+this.name);
flag=false;
notifyAll();
}
}
//DuckProductor
public class DuckProductor implements Runnable {
RoastDuck rd;
public DuckProductor(RoastDuck rd) {
this.rd = rd;
}
@Override
public void run() {
while (true){
rd.produce("烤鸭");
}
}
}
//DuckConsumer
public class DuckConsumer implements Runnable {
RoastDuck rd;
public DuckConsumer(RoastDuck rd) {
this.rd = rd;
}
@Override
public void run() {
while (true){
rd.consume();
}
}
}
//main
RoastDuck rd = new RoastDuck();
DuckProductor dp = new DuckProductor(rd);
DuckConsumer dc = new DuckConsumer(rd);
Thread t0 = new Thread(dp);
Thread t1 = new Thread(dp);
Thread t2 = new Thread(dc);
Thread t3 = new Thread(dc);
t0.start();
t1.start();
t2.start();
t3.start();
重点在于 while notifyAll的理解
- while 解决线程获取执行权后是否要运行,如果是if,醒来后不会判断flag,直接执行后面代码,所以有问题
- notify只会唤醒一个线程,如果是本方,就容易出现等待死锁;notifyAll解决本方线程可以唤醒对方线程
JDK1.5-lock
将同步和锁封装成了对象,并将操作锁的隐式方法显示化
- Lock:替代了同步代码块或函数;将同步锁的隐式操作变成显示操作,更为灵活,可以一个锁提供多个监视器,unlock需要定义在finally中
- Condition:替代Object中的wait、notify等方法,可以任意锁组合
await singal singalAll
//RoastDuck
public class RoastDuck {
private String name;
private int count = 1;
private boolean flag=false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition com_con = lock.newCondition();
public void produce(String name){
lock.lock();
try {
while(flag){
try {
pro_con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
count++;
System.out.println("producer5.0..."+Thread.currentThread().getName()+"..."+this.name);
flag=true;
com_con.signal();
}finally {
lock.unlock();
}
}
public void consume(){
lock.lock();
try {
while(!flag){
try {
com_con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("consumer5.0..."+Thread.currentThread().getName()+"..."+this.name);
flag=false;
pro_con.signal();
}finally {
lock.unlock();
}
}
}
锅盔
/**
* @author yuankun
* @date 2018.12.21
* @Description 锅盔资源类-每次只提供一个锅盔
*/
public class GuoKui {
private int counter = 0;
private String name;
private boolean flag = false;
// 生产者
public synchronized void Product(String name){
// 如果有锅盔则等待消费
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//生产锅盔
counter++;
this.name = name + counter;
flag = true;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name+" | 有锅盔了快来买!");
notifyAll();
}
// 消费者
public synchronized void consume(){
// 没有锅盔就等待生产
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag = false;
System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name+" | 锅盔被买走!");
notifyAll();
}
}
/**
* @author yuankun
* @date 2018.12.21
* @Description 生产者线程类,调用Guokui资源
*/
public class Product implements Runnable {
private GuoKui gk;
private Thread t;
public Product(GuoKui gk) {
this.gk = gk;
t = new Thread(this);
t.start();
}
public void run() {
for(int i=0;i<10;i++){
gk.Product("袁琨牌大锅盔");
}
}
}
/**
* @author yuankun
* @date 2018.12.21
* @Description 消费者线程类,调用Guokui资源
*/
public class Consumer implements Runnable {
private GuoKui gk;
private Thread t;
public Consumer(GuoKui gk) {
this.gk = gk;
t = new Thread(this);
t.start();
}
public void run() {
for(int i=0;i<10;i++){
gk.consume();
}
}
}
/**
* @author yuankun
* @date 2018.12.21
* @Description 执行类
*/
public class Sell_Guokui {
public static void main(String args[]){
GuoKui gk = new GuoKui();
new Product(gk);
new Consumer(gk);
}
}
生产者消费者2
/**
* 共享对象Goods
* @author Administrator
*
*/
public class Goods {
private String brand;
private String name;
private boolean isFlag;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Goods(String brand, String name) {
super();
this.brand = brand;
this.name = name;
}
public Goods() {
super();
}
public synchronized void set(String brand, String name) {
if(isFlag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setBrand(brand);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setName(name);
this.notifyAll();
isFlag=true;
}
public synchronized void get() {
if(!isFlag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者消费了"+this.getBrand()+this.getName());
notifyAll();
isFlag=false;
}
}
/**
* 生产者
* @author Administrator
*
*/
public class Produce implements Runnable {
private Goods goods;
public Produce(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
for(int i=0;i<10;i++) {
if(i%2==0) {
goods.set("北京", "烤鸭");
}else {
goods.set("成都", "兔头");
}
System.out.println("生产者生产了"+goods.getBrand()+goods.getName());
}
}
}
/**
* 消费者
* @author Administrator
*
*/
public class Consume implements Runnable {
private Goods goods;
public Consume(Goods goods) {
super();
this.goods = goods;
}
@Override
public void run() {
for(int i=0;i<10;i++) {
goods.get();
}
}
}
//测试类
public class Test {
public static void main(String[] args) throws InterruptedException {
Goods goods = new Goods();
Produce produce = new Produce(goods);
Consume consume = new Consume(goods);
Thread tpThread = new Thread(produce);
Thread tcThread = new Thread(consume);
tpThread.start();
Thread.sleep(100);
tcThread.start();
}
}
包子
包子资源类:
public class BaoZi {
String pier ;
String xianer ;
boolean flag = false ;//包子资源 是否存在 包子资源状态
}
吃货线程类:
public class ChiHuo extends Thread{
private BaoZi bz;
public ChiHuo(String name,BaoZi bz){
super(name);
this.bz = bz;
}
@Override
public void run() {
while(true){
synchronized (bz){
if(bz.flag == false){//没包子
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("吃货正在吃"+bz.pier+bz.xianer+"包子");
bz.flag = false;
bz.notify();
}
}
}
}
包子铺线程类:
public class BaoZiPu extends Thread {
private BaoZi bz;
public BaoZiPu(String name,BaoZi bz){
super(name);
this.bz = bz;
}
@Override
public void run() {
int count = 0;
//造包子
while(true){
//同步
synchronized (bz){
if(bz.flag == true){//包子资源 存在
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 没有包子 造包子
System.out.println("包子铺开始做包子");
if(count%2 == 0){
// 冰皮 五仁
bz.pier = "冰皮";
bz.xianer = "五仁";
}else{
// 薄皮 牛肉大葱
bz.pier = "薄皮";
bz.xianer = "牛肉大葱";
}
count++;
bz.flag=true;
System.out.println("包子造好了:"+bz.pier+bz.xianer);
System.out.println("吃货来吃吧");
//唤醒等待线程 (吃货)
bz.notify();
}
}
}
}
测试类:
public class Demo {
public static void main(String[] args) {
//等待唤醒案例
BaoZi bz = new BaoZi();
ChiHuo ch = new ChiHuo("吃货",bz);
BaoZiPu bzp = new BaoZiPu("包子铺",bz);
ch.start();
bzp.start();
}
}