一 看个简单例子
开启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();
}
}