并发-----java多线程理解与总结

------- android培训java培训、期待与您交流! ----------

多线程Thread:一个进程中拥有多个可执行路径,一个程序至少有一个进程,而一个进程至少有一个线程;

java对多线程的支持方案:1继承Thread类,2实现Runnable方法

特点:由于线程是程序的多条执行路径,所以执行权CPU说了说,多线程具有随机性和并发性

Thread类概述:

  1. run()方法概述:这个方法里封装了线程要执行的代码,也就是说我们将想要多线程执行的代码的地方,如果对象直接调用则不是多线程;
  2. start()方法:让线程就绪,执行run()方法体;
  3. 在线程就绪前,也就是start()调用前,我们可以设置线程的优先级,守护线程等,易于理解
  4. isLive()测试线程是否是激活状态
  5. interrupt(),中断线程
  6. thread类试图通过自己的方法来控制线程合理的在理想状态下执行,但是cpu的多核多线程技术使得他不可能理想的完成,所以,其他的方法就看api了解
  7. 线程的生命周期图

cpu操作是具有原子性的,所以判断线程时候存在问题的条件为:

  • 是否是多线程 ,这个必须是,因为我们编写的就是多线程程序
  • 是否有共享代码,从这一步就要考虑问题的存在了,因为每个线程都有自己的栈内存,程序计数器等
  • 是否是同一把锁,这个往往被忽略,但是jdk5出现的显示的锁,一般这一步不会出错了;
  • 是否有多条语句操作共享语句,解决问题的根本所在了

解决问题的方法:同步代码块,同步方法。前提:多线程,同一把锁

格式: 1synchronized(对象){}        2public synchronized void  方法名(){}

还是卖票吧,只不过我将飘封装称了类,稍微有点不同

1票类:

<span style="white-space:pre">	</span>public class Ticket {
	//张数
	private int number;
	//票价
	private float price;
	public Ticket(int number) {
		this.number=number;
	}//get  set省略
2卖票具体线程类:

public class SaleTicke implements Runnable {
	private Ticket t;
	public SaleTicke(Ticket t) {
		this.t = t;
	}
	@Override
	public void run() {
		//这个不是共享数据
		//int sx=t.getNumber(),并且用sx来判断,各自的栈内存都会有这么一个变量,所以会出现卖200张票
		while (true) {
<span style="white-space:pre">			</span>//将所有操作的资源的语句全部用同步代码块包裹
			synchronized (this) {
				if (t.getNumber() > 0) {
					System.out.println(Thread.currentThread().getName()
							+ "出售了第" + (t.getNumber()) + "张票");
					//卖一张,减少一张,就这里不同
					t.setNumber(t.getNumber() - 1);
				} else {
					break;//run()方法结束,线程结束,jvm结束
				}}}}}

3卖票测试类:
<span style="white-space:pre">	</span>public static void main(String[] args) {
		Ticket resource =new Ticket(100);
		SaleTicke st=new SaleTicke(resource);
		Thread t1=new Thread(st,"窗口-1");
		Thread t2=new Thread(st,"窗口-2");
		t1.start();
		t2.start();
	}
4卖票总结:当票被封装为类时,第二种安全因素就诞生了,以及在取出值之后要调用set方法来重新设置

5线程间通信:等待唤醒机制,运用jdk5新特性,生产者,消费者

/**
 *	资源类
 */
public class Resource {
	//资源名
	private String name;
	//数量
	private int count=0;
	//标记
	private boolean flag=false;
	//锁
	private Lock lock=new ReentrantLock();
	private Condition set=lock.newCondition();
	
	public Resource(){}
	//创造资源
	public void creatResource() throws InterruptedException{
		lock.lock();
		try {
			//if只判断一次,在这里用不合适
			while(flag)//有,等
				set.await();
			++count;
			System.out.println(Thread.currentThread().getName()+"-----生产第"+count+"个商品");
			//重置标记
			flag=true;
			//唤醒
			set.signal();
		} 
		finally{
			lock.unlock();
		}
	}
	//消费
	public void useRes() throws InterruptedException{
			lock.lock();
			try {
				while(!flag)//没有,等
					set.await();
				System.out.println(Thread.currentThread().getName()+"正在消费第" + count + "商品");
				//重置标记
				flag=false;
				//唤醒
				set.signal();
			} 
			finally{
				lock.unlock();
			}
	}
}
/**
 * 生产者
 */
public class Creat implements Runnable{
	private Resource r=null;
	public Creat(Resource r){
		this.r=r;
	}
	public Creat(){
	}
	@Override
	public void run() {
		while(true){
			try {
				r.creatResource();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();}}}
}
/**
 * 消费者
 */
public class Use implements Runnable{
	private Resource r = null;
	public Use(Resource r) {
		this.r = r;
	}
	public Use() {	
	}
	@Override
	public void run() {
		while(true){try {r.useRes();} catch (InterruptedException e) {e.printStackTrace();}}}}
/**
 * 测试类
 */
public class UseTest {
	public static void main(String[] args) {
		Resource r=new Resource();
		Creat c=new Creat(r);
		Use u=new Use(r);
		new Thread(c,"生产者").start();
		new Thread(u,"消费者").start();}
}

结果:
生产者-----生产第26911个商品
消费者正在消费第26911商品
生产者-----生产第26912个商品
消费者正在消费第26912商品
生产者-----生产第26913个商品
消费者正在消费第26913商品
生产者-----生产第26914个商品
消费者正在消费第26914商品
生产者-----生产第26915个商品
消费者正在消费第26915商品
生产者-----生产第26916个商品
消费者正在消费第26916商品
生产者-----生产第26917个商品
消费者正在消费第26917商品
生产者-----生产第26918个商品
消费者正在消费第26918商品
生产者-----生产第26919个商品
消费者正在消费第26919商品
生产者-----生产第26920个商品
消费者正在消费第26920商品

死锁:锁嵌套使用导致

public class DieLock {

	public static void main(String[] args) {
		new MyThread(true).start(); 
		new MyThread(false).start(); 
	}

}

class Lock {
	public static final Object lock1 = new Object();
	public static final Object lock2 = new Object();
}

class MyThread extends Thread {
	private boolean flag = false;
	MyThread(boolean b){
		this.flag=b;
	}
	public void run() {
		if (flag) {//锁1嵌套锁2
			synchronized (Lock.lock1) {
					System.out.println("锁1.....");
				synchronized (Lock.lock2) {
					System.out.println("锁12..........");
				}
			}
		} else {//锁2嵌套锁1
			synchronized (Lock.lock2) {
				System.out.println("锁2||||||||");
				synchronized (Lock.lock1) {
					System.out.println("锁22||||||||||||");
				}
			}

		}
	}
}

总结:

1清楚的讲,多线程让我的头大了许多,非常不理解为什么会出错,调试比较难受,啊,真的炸了,最后,一步步分析,判断,找出问题出现的地方并且对症下药才可以;

2那四个判断条件是多么的重要:在写一次

  • 是否是多线程 (是否同时加锁),这个必须是,因为我们编写的就是多线程程序
  • 是否有共享代码,从这一步就要考虑问题的存在了,因为每个线程都有自己的栈内存,程序计数器等
  • 是否是同一把锁,这个往往被忽略,但是jdk5出现的显示的锁,一般这一步不会出错了;
  • 是否有多条语句操作共享语句,解决问题的根本所在了

------- android培训java培训、期待与您交流! ----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值