Java初学总结(二十五)

资源共享

1.继承Thread类所创建的线程不能实现资源共享功能

public class MyThread extends Thread{
	//定义车票【共享资源】
	private int  piao=5;
	@Override
	public void run() {
		while(piao>0) {
				//我们通过线程的暂停来模拟
				//收钱-->打票-->找钱
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+
						"--卖出1张票,还剩"+(--piao)+"张");
		}
	}
}
package com.wangxing.test1;
public class TestMain1 {
	public static void main(String[] args) {
		MyThread th1=new MyThread();
		MyThread th2=new MyThread();
		MyThread th3=new MyThread();
		th1.setName("窗口1");
		th2.setName("窗口2");
		th3.setName("窗口3");
		th1.start();
		th2.start();
		th3.start();
	}
}

在这里插入图片描述

2.通过实现Runnable接口所创建的线程可以实现资源共享功能

package com.wangxing.test2;
public class MyThread implements Runnable{
	//定义车票【共享资源】
	private int  piao=5;
	@Override
	public void run() {
		while(piao>0) {
			//我们通过线程的暂停来模拟
			//收钱-->打票-->找钱
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+
					"--卖出1张票,还剩"+(--piao)+"张");
		}
	}
}
package com.wangxing.test2;
public class TestMain2 {
	public static void main(String[] args) {
		//创建目标对象
		MyThread  mth=new MyThread();
		//创建线程对象
		Thread th1=new Thread(mth);
		Thread th2=new Thread(mth);
		Thread th3=new Thread(mth);
		//设置线程名称
		th1.setName("窗口1");
		th2.setName("窗口2");
		th3.setName("窗口3");
		//开启线程
		th1.start();
		th2.start();
		th3.start();
	}
}

在这里插入图片描述
通过上面的实现Runnable接口的买票程序可以实现资源共享,但是卖出会卖出剩下负数的情况。当多条线程,同时访问同一个资源的时候,会产生数据不一致的错误情况。

3.为什么需要线程同步/线程安全?
因为当多条线程,同时访问同一个资源的时候,会产生数据不一致的错误情况。为了解决这种数据不一致的错误情况,我们才学习线程同步。

4.什么是线程同步/线程安全?
当多条线程同时访问同一个资源的时候,每一次只能由的其中一条线程访问公共资源,其他的线程都处于等待状态,当这一条线程访问完后,其他线程中的一条才能访问,剩下的线程继续等待当前线程访问结束,实现这个过程就是线程同步。

5.线程同步/线程安全的实现方式有几种,分别是什么,有什么区别?

(1)同步代码块
格式:
synchronized(同步对象){
}

package com.wangxing.test3;
public class MyThread implements Runnable{
	//定义车票【共享资源】
	private int  piao=5;
	@Override
	public void run() {
		//同步代码块
		synchronized (this) {
			while(piao>0) {
				//我们通过线程的暂停来模拟
				//收钱-->打票-->找钱
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+
						"--卖出1张票,还剩"+(--piao)+"张");
			}
		}
	}
}

在这里插入图片描述

同步代码块虽然可以实现买票的效果,但是它在使用的时候,需要设置一个同步对象,由于我们很多时候都不知道这个同步对象应该是谁,容易写错,造成死锁的情况。正是应为这个缺点,我们很少使用同步代码块来实现线程同步。
(2)同步方法
同步方法的定义格式:
访问限制修饰符 synchronized 方法返回值类型 方法名称(){
}

package com.wangxing.test4;
public class MyThread implements Runnable{
	//定义车票【共享资源】
	private int  piao=5;
	private  boolean  flag=true;
	@Override
	public void run() {
			while(flag) {
				sellPiao();
			}
	}
	/**
	  * 买票的同步方法
	 */
	public  synchronized  void  sellPiao() {
		if(piao>0) {
		//我们通过线程的暂停来模拟
		//收钱-->打票-->找钱
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+
				"--卖出1张票,还剩"+(--piao)+"张");
		}else {
			flag=false;
		}
	}
}

在这里插入图片描述

(3)通过Lock接口
Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作
常用的接口方法
在这里插入图片描述
由于上面的锁方法是Lock接口,我们要使用就得先创建出Lock接口对象,由于Lock是个接口不能new ,我们就得使用它的子类ReentrantLock来创建对象。

package com.wangxing.test5;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyThread implements Runnable{
	//定义车票【共享资源】
	private int  piao=5;
	//创建Lock对象
	private  Lock  lock=new ReentrantLock();
	@Override
	public void run() {
		lock.lock();
		while(piao>0) {
			//我们通过线程的暂停来模拟
			//收钱-->打票-->找钱
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+
						"--卖出1张票,还剩"+(--piao)+"张");
			}
		lock.unlock();
	}
}

在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值