多线程——问题引出以及解决方法

1,,多个窗口一起买1000张票,出现线程安全问题--------解决方法:同步

public class f1Tickets {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
	}
}
class tickets extends Thread{//以后开发 必须使用Runnable创建线程
	static int totals = 100;//当static 不存在的时候不会出现安全问题 因为没有操作共享数据
	public void run(){
		while (true) {
			if(totals>0){
			//需要让线程等待一下才容易看到效果
			try {
				Thread.sleep(100);
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"票还剩下:。。"+totals--);
			}
		}
	}
}
/*
 * Thread-6票还剩下:。。3
Thread-4票还剩下:。。2
Thread-5票还剩下:。。1
Thread-0票还剩下:。。0
Thread-1票还剩下:。。-1
Thread-3票还剩下:。。-2
Thread-6票还剩下:。。-3
Thread-2票还剩下:。。-4
Thread-4票还剩下:。。-5
 * 
 * */
解决办法 同步
public class f1Tickets {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();
		new tickets().start();

	}
}
class tickets extends Thread{
	static int totals = 100;//当static 不存在的时候不会出现安全问题 因为没有操作共享数据
	public void run(){
		while (true) {
			synchronized (tickets.class) {//同步的重要前提是  多线程操作共享数据,多线程同一把锁
				if(totals>0){
				//需要让线程等待一下才容易看到效果
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"票还剩下:。。"+totals--);
				}
				
			}
		}
	}
}

2,性别错位问题引出——等待唤醒机制
出现问题:性别张冠李戴

public class f1WaitAndSingle {
	public static void main(String[] args) {
		new Thread(new Set()).start();
		new Thread(new Out()).start();
	}
}
class Info{
	String name ;
	String sex;
	private static Info info = new Info();
	public static Info getInstance(){
		return info;
	}
	public void sop(){
		System.out.println(name+",,,,,"+sex);
	}
}
class Set implements Runnable{
	@Override
	public void run() {
		Info info = Info.getInstance();
		int x = 1;
		while (true) {
			if (x==1) {
				info.name = "百里屠苏:---";
				info.sex = "man";
			} else {
				info.name = "风晴雪:---";
				info.sex = "女生";
			}
//			x = (x+1)%2;
			x = x^2;
		}
	}
}
class Out implements Runnable{
	public void run() {
		Info info = Info.getInstance();
		while (true) {
			info.sop();
		}
	}
}

/*出问题的原因:当设置线程只设置好姓名而没设置好性别的时候  执行权被输出线程抢走
 *  输出线程输出当前设置好的名字和上一次设置的性别 导致问题的产生
 * 百里屠苏:---,,,,,man
百里屠苏:---,,,,,man
风晴雪:---,,,,,女生
百里屠苏:---,,,,,女生
风晴雪:---,,,,,man
风晴雪:---,,,,,女生
百里屠苏:---,,,,,女生
风晴雪:---,,,,,女生
 * */

解决方法:等待唤醒机制

public class f2WaitAndSingle {
		public static void main(String[] args) {
			new Thread(new Set2()).start();
			new Thread(new Out2()).start();
		}
	}
	class Info2{
		String name ;
		String sex;
		boolean flag;
		private static Info2 info = new Info2();
		public static Info2 getInstance(){
			return info;
		}
		public void sop(){
			System.out.println(name+",,,,,"+sex);
		}
	}
	
	
	//解决问题的办法 1:先设置好人和性别   然后输出   建立一个标记表明设置好了  和输出好了
//	class Set2 implements Runnable{
//		@Override
//		public void run() {
//			Info2 info = Info2.getInstance();
//			int x = 1;
//			while (true) {
//				if(!info.flag){
//					if (x==1) {
//						info.name = "百里屠苏:---";
//						info.sex = "man";
//					} else {
//						info.name = "风晴雪:---";
//						info.sex = "女生";
//					}
					x = (x+1)%2;
//					x = x^2;
//					info.flag = true;
//				}
//			}
//		}
//	}
//	class Out2 implements Runnable{
//		public void run() {
//			Info2 info = Info2.getInstance();
//			while (true) {
//				if(info.flag){
//					info.sop();
//					info.flag = false;
//				}
//			}
//		}
//	}
//	解决问题的方式2,等待唤醒机制
	class Set2 implements Runnable{
		@Override
		public void run() {
			Info2 info = Info2.getInstance();
			int x = 1;
			while (true) {
				synchronized (info) {
					if(!info.flag)
						try {
							info.wait();
						} catch (Exception e) {
							e.printStackTrace();
						}
						if (x==1) {
							info.name = "百里屠苏:---";
							info.sex = "man";
						} else {
							info.name = "风晴雪:---";
							info.sex = "女生";
						}
//						x = (x+1)%2;
						x = x^2;
						info.flag = false;//让本线程下一次进入wait等待状态
						info.notify();//唤醒info所监视的一个线程  此时就是 正在等待状态的 Out2线程
				}
			}
		}
	}
	class Out2 implements Runnable{
		public void run() {
			Info2 info = Info2.getInstance();
			while (true) {
				synchronized (info) {
					if(info.flag)//该if语句的方法体是 wait
						try {
							info.wait();
						} catch (Exception e) {
							e.printStackTrace();
						}
						info.sop();
						info.flag = true;//让本线程下一次进入wait等待状态	
						info.notify();//唤醒info所监视的一个线程  此时就是 正在等待状态的 Set2线程
				}
			}
		}
	}
生产者与消费者:保证线程安全  使用新锁实现
public class f1ProducterAndConsumer {

	public static void main(String[] args) {
		new Thread(new Productor(),"生产者").start();
		new Thread(new Consumer(),"消费者").start();
//		new Thread(new Productor(),"生产者2").start();
//		new Thread(new Consumer(),"消费者2").start();
//当出现多生产者多消费者的时候会出现 生产一个商品被消费两次  或者生产两个商品只有一个被消费		
	}
}
class Reso{
	int count;
	boolean flag;
	private static Reso res = new Reso();
	public static Reso getReso(){
		return res;
	}
	Lock lock = new ReentrantLock();
	Condition conP = lock.newCondition();
	Condition conS = lock.newCondition();
	public void produce(){
		while (true) {
			lock.lock();
			if (!res.flag)
				try {
					conP.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			res.count++;
			System.out.println(Thread.currentThread().getName()+"生产一个商品:"+res.count);
			res.flag = false;
			conS.signal();
		}
	}
	public void consum(){
		while (true) {
			lock.lock();
			if (res.flag)
				try {
					conS.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			System.out.println(Thread.currentThread().getName()+"xiaofei一个商品:"+res.count);
			res.flag = true;
			conP.signal();
		}
	}
}
class Productor implements Runnable{
	public void run() {
		Reso res = Reso.getReso();
		res.produce();
	}
}
class Consumer implements Runnable{

	@Override
	public void run() {
		Reso res = Reso.getReso();
		res.consum();
	}
}

生产者与消费者:保证线程安全  使用新锁实现

public class f1ProductorsAndConsumers {
		public static void main(String[] args) {
			new Thread(new Productors(),"生产者").start();
			new Thread(new Consumers(),"消费者").start();
			new Thread(new Productors(),"生产者2").start();
			new Thread(new Consumers(),"消费者2").start();
			new Thread(new Productors()).start();
			new Thread(new Consumers()).start();
			new Thread(new Productors()).start();
			new Thread(new Consumers()).start();
			new Thread(new Productors()).start();
			new Thread(new Consumers()).start();
			new Thread(new Productors()).start();
			new Thread(new Consumers()).start();
			new Thread(new Productors()).start();
			new Thread(new Consumers()).start();
		//当出现多生产者多消费者的时候会出现 生产一个商品被消费两次  或者生产两个商品只有一个被消费		
		}
	}
	class Resource2{
		int count;
		boolean flag;
		private static Resource2 res = new Resource2();
		public static Resource2 getInstance(){
			return res;
		}
		
		Lock lock = new ReentrantLock();
		Condition conP = lock.newCondition();
		Condition conS = lock.newCondition();
		public void product(){
			while (true) {
				lock.lock();
				while (!flag)//因为不知一个线程会执行这代码  多个线程等待  因为可能有一个线程把标记给改了 
					try {
						conP.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				count++;
				System.out.println(Thread.currentThread().getName()+"生产一个商品:"+res.count);
				flag = false;
				conS.signal();
			}
		}
		public void consume(){
			while (true) {
				lock.lock();
				if(flag)
					try {
						conS.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				System.out.println(Thread.currentThread().getName()+"xiaofei一个商品:"+res.count);
				res.flag = true;
				conP.signal();
			}
		}
	}
	class Productors implements Runnable{
		public void run() {
			Resource2 res = Resource2.getInstance();
			res.product();
		}
	}
	class Consumers implements Runnable{
	  public void run() {
		  Resource2 res = Resource2.getInstance();
		  res.consume();
  	}		
  }










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值