一 看个简单例子
开启2个线程
一个叫线程A
一个叫线程B
要求
先打印5遍 我是线程B
再打印5遍 我是线程A
总结:解题思路
1.先按题意 搭架子.
2.执行 查看结果
3.分析结果出现的问题
4.把出现问题的 这次进入线程的顺序记录下来
5.具体问题具体分析
public class Demo01 { public static void main(String[] args) { ABRunnable runnable =new ABRunnable(); Thread t1 = new Thread(runnable,"线程A"); Thread t2 = new Thread(runnable,"线程B"); t1.start(); t2.setPriority(10); t2.start(); } } class ABRunnable implements Runnable{ //声明一个标记 解决A先进来的问题 private boolean isflag = false; //声明一个锁 Object obj = new Object(); @Override public void run() { //循环打印线程名 String name = Thread.currentThread().getName(); System.out.println(name+"进来了"); //加同步锁 //运行结果很随机 (有时候会卡住) //打印 结果得到 A进来 会卡住 //A先进来 执行打印 B再进来 不让它等待 直接打印进行 // // B先进来 运行正确 synchronized (obj) { //判断线程 if (name.equals("线程B")&& !isflag) { try { obj.wait(); //如果B线程等待是还持有锁 :线程会卡住.从打印结果看到 A 线程也可以进来 //当线程进入等待时会释放锁 //从那个位置等待的 //就从哪个位置被唤醒 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for (int i = 0; i < 5; i++) { System.out.println(name); } //修改标记 如果线程A打印完了 线程B就不需要等待了直接打印就行 //打印完成后唤醒B if (name.equals("线程A")) { isflag = !isflag; } obj.notify(); //随机唤醒一个等待中的线程 // notifyAll 唤醒所有等待的线程 } } }
package com.lanou3g; /* * Person类 姓名 性别 * 开启两个线程 * 一个对Person对象进行赋值 * 一个对Person对象进行打印 * 要求 * 一次打印 大海 男 * 一次打印 zhengshuang nv * 间隔输出 */ public class Demo02 { public static void main(String[] args) { //注意保证赋值和打印的对象时同一个对象 //把同一个对象 当做参数 传入线程中操作 //保证使用同一把锁 //注意,如果打印线程先进来了 要先等待 赋值线程赋值完毕 在进行打印. //标记 传递信息 保证两个线程使用同一个标记 //为了使用同一个标记 声明在person内. Person p = new Person(); SetRunnnable sr = new SetRunnnable(p); PrintRunnable pr = new PrintRunnable(p); Thread t1 = new Thread(sr); Thread t2 = new Thread(pr); t1.start(); t2.start(); } } //创建赋值线程 class SetRunnnable implements Runnable{ //声明标识 间隔赋值 private boolean isMan = false; //声明 person对象 private Person p; public SetRunnnable() { super(); } public SetRunnnable(Person p) { super(); this.p = p; } @Override public void run() { while (true) { synchronized (p) { if (p.flag) { try { p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //间隔赋值 if (!isMan) { //赋值大海 p.name = "大海"; p.gender = "男"; }else { //赋值郑爽 p.name = "zhengshuang"; p.gender = "nv"; } isMan = !isMan; p.flag = true; p.notify(); } } } } //创建打印线程 class PrintRunnable implements Runnable{ private Person p; public PrintRunnable() { super(); // TODO Auto-generated constructor stub } public PrintRunnable(Person p) { super(); this.p = p; } @Override public void run() { while (true) { synchronized (p) { if (!p.flag) { try { p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(p.name+"----"+p.gender); p.flag = false; p.notify(); } } } } class Person{ public String name; public String gender; public boolean flag = false; }
保姆听音乐做家务
程序开始 打印音乐开始 并且每隔1秒 打印动次打次 直到蹲起完成
保姆类
保姆 来到洗衣间 衣服放入洗衣机
洗衣机开始洗衣服 5次(1秒打印一次洗衣中...)
然后 保姆来到客厅 扫地 12次(1秒打印一次扫地中...)
洗衣机洗衣服 不影响保姆去客厅扫地
然后 保姆去晒衣间 晒衣服 2次(1秒打印一次晒衣服中...)
(要求洗衣机洗完衣服 保姆也要扫完地才能去晒衣服)
然后打印 家务处理完毕
保姆开始健身
然后 保姆开始做 蹲 起 10次(交替 打印 蹲 起 各5次)
提示:
1.每一个类都是一个线程
2.保姆类也是线程相当于线程管理类
3.中间用到了一些方法(先看看啥意思 然后测试一下在用)
setDaemon();
join();
wait();
notify();
延时类:
public class TimeWait { public static void time( long t) { long c = System.currentTimeMillis(); while (System.currentTimeMillis()-c<t) { } } }
听音乐类:
public class Music implements Runnable { @Override public void run() { //每隔一秒打印动次打次 System.out.println("音乐开始"); while (true) { TimeWait .time(1000); System.out.println("嘀哩嘀哩滴滴嘀哩嘀哩"); } } }
洗衣服线程类
public class XY implements Runnable { @Override public void run() { System.out.println("来到洗衣房 洗衣开始"); for (int i = 0; i < 5; i++) { TimeWait.time(1000); System.out.println("洗衣中/....."); } System.out.println("洗衣结束"); } }
public class XY implements Runnable { @Override public void run() { System.out.println("来到洗衣房 洗衣开始"); for (int i = 0; i < 5; i++) { TimeWait.time(1000); System.out.println("洗衣中/....."); } System.out.println("洗衣结束"); } }
晒衣服线程类:
public class SY implements Runnable { @Override public void run() { System.out.println("来到晒一间 晾衣开始"); for (int i = 0; i < 2; i++) { TimeWait.time(1000); System.out.println("晾衣中/....."); } System.out.println("晾衣结束"); } }
保姆线程类:
保姆作为线程管理类在线程内创建其他线程
/* * 线程管理类 * 组装各个类的方法 */ public class BM implements Runnable{ //定义标记 public boolean flag = false; //计数 public int num =0; @Override public void run() { // 组装洗衣 拖地的 ...方法 Music music = new Music(); Thread mThread = new Thread(music); //设置守护线程 mThread.setDaemon(true); //开启线程 mThread.start(); //洗衣 XY xy = new XY(); Thread txy = new Thread(xy); txy.start(); //扫地 SD sd = new SD(); Thread tsd = new Thread(sd); tsd.start(); //洗衣机洗完衣服 保姆也要扫完地才能去晒衣服 try { txy.join(); tsd.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //晒衣服 SY sy = new SY(); Thread tsy = new Thread(sy); tsy.start(); try { tsy.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Dun dun = new Dun(this); QI qi = new QI(this); Thread t1 = new Thread(dun); Thread t2 = new Thread(qi); t1.start(); t2.start(); } } //蹲类 class Dun implements Runnable{ private BM bm; public Dun() { super(); } public Dun(BM bm) { super(); this.bm = bm; } @Override public void run() { while (true) { synchronized (bm) { bm.num++; if (bm.num>10) { break; } //等待 if (bm.flag==true) { try { bm.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //打印 TimeWait.time(1000); System.out.println("蹲-------"); //唤醒 bm.flag = true; bm.notify(); } } } } //起类 class QI implements Runnable{ private BM bm; public QI(BM bm) { super(); this.bm = bm; } public QI() { super(); // TODO Auto-generated constructor stub } @Override public void run() { while (true) { synchronized (bm) { bm.num++; if (bm.num==10) { break; } if (bm.flag ==false) { try { bm.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } TimeWait.time(1000); System.out.println("起......"); bm.flag = false; bm.notify(); } } } }
测试类
public class Test { public static void main(String[] args) { BM b = new BM(); Thread tb = new Thread(b); System.out.println("保姆开始做家务"); tb.start(); } }