Java 基础学习之多线程(二) 并发问题和线程通讯

一 看个简单例子

开启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();
	}

}











猜你喜欢

转载自blog.csdn.net/vlin_fan/article/details/80614504